【问题标题】:SQL Server - Delete unused rowsSQL Server - 删除未使用的行
【发布时间】:2010-08-24 04:42:29
【问题描述】:

我需要获取存储过程(不是标准的,只有自定义的)来删除未使用的行表(table1)和其他一些表(table2、table3、table4...- 我们不知道有多少表引用通过 FOREIGN KEY CONSTRAINT 到 table1) 可以引用这个表。

例如:

СREATE PROCEDURE [dbo].[delete_on_constraints]
@table varchar(36) – table name we need to delete unused rows
@column varchar(36) – column name - primary key, on which other tables refers by FOREIGN KEY CONSTRAINT

有table1和table2,table3引用table1(提醒,我们不知道有多少表通过FOREIGN KEY CONSTRAINT引用table1)

CREATE TABLE [table1] (
    [id] [int] IDENTITY (1, 1) NOT NULL CONSTRAINT [PK_ table1] PRIMARY KEY,
    [value] [int] NULL 
)
GO

CREATE TABLE [table2] (
    [id] [int] IDENTITY (1, 1) NOT NULL CONSTRAINT [PK_ table2] PRIMARY KEY,
    [table1_id] [int] NOT NULL ,
       CONSTRAINT [FK_ table2_ table1] FOREIGN KEY ([table1_id]) REFERENCES [table1] ( [id] ) 
) 
GO 

CREATE TABLE [table3] (
    [id] [int] IDENTITY (1, 1) NOT NULL CONSTRAINT [PK_ table3] PRIMARY KEY,
    [table1_id] [int] NOT NULL ,
       CONSTRAINT [FK_ table3_ table1] FOREIGN KEY ([table1_id]) REFERENCES [table1] ( [id] ) 
)

GO 
INSERT INTO [table1] VALUES (100)
INSERT INTO [table1] VALUES (200)
INSERT INTO [table1] VALUES (300)
INSERT INTO [table1] VALUES (400)

GO
INSERT INTO [table2] VALUES (1)
INSERT INTO [table2] VALUES (3)

GO
INSERT INTO [table3] VALUES (1)
INSERT INTO [table3] VALUES (2)
INSERT INTO [table3] VALUES (3)

表中有行调用存储过程

table1
id value
1 100
2 200
3 300
4 400

table2
id table1_id
1 1
2 3

table3
id table1_id
1 1
2 2
3 3

之后 [dbo].[delete_on_constraints] 'table1' 'id' 过程调用

table1

id       value
1        100
2        200
3        300

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    首先,让我郑重声明,此代码绝不应在生产中使用。我的意思是,它应该只用作一次性清理。如果您经常需要在不知道 DRI 的情况下删除行,则存在一个基本的设计问题。

    简而言之,您需要使用动态 SQL 来查询关系并构建 Delete 语句。

    Declare @Columns Cursor
    Declare @PKTableSchema nvarchar(128)
    Declare @PKTableName nvarchar(128)
    Declare @PKColumnName nvarchar(128)
    Declare @TableSchema nvarchar(128)
    Declare @TableName nvarchar(128)
    Declare @ColumnName nvarchar(128)
    Declare @Sql nvarchar(max)
    
    Set @Columns = Cursor Fast_Forward For
        Select Quotename(PK_CCU.TABLE_SCHEMA)
            , Quotename(PK_CCU.TABLE_NAME)
            , Quotename(PK_CCU.COLUMN_NAME)
            , Quotename(RC_CCU.TABLE_SCHEMA)
            , Quotename(RC_CCU.TABLE_NAME)
            , Quotename(RC_CCU.COLUMN_NAME)
        From INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS As RC
            Join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As RC_CCU
                On RC_CCU.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA
                    And RC_CCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
            Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As TC
                On TC.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA
                    And TC.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME
                    And TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
            Join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As PK_CCU
                On PK_CCU.CONSTRAINT_SCHEMA = TC.CONSTRAINT_SCHEMA
                    And PK_CCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
        Where PK_CCU.TABLE_SCHEMA = 'dbo'
            And PK_CCU.TABLE_NAME = @TableParam
            And PK_CCU.COLUMN_NAME = @ColumnParam
    
    Open @Columns 
    Fetch Next From @Columns Into @PKTableSchema, @PKTableName, @PKColumnName, @TableSchema, @TableName, @ColumnName
    
    Set @Sql = 'Delete ' + @PKTableSchema + '.' + @PKTableName 
        + ' Where 1 = 1' 
    
    While @@Fetch_Status = 0
    Begin
        Set @Sql = @Sql + Char(13) + Char(10)
            + ' And Not Exists ( Select 1 From ' + @TableSchema + '.' + @TableName
                                + ' Where ' + @ColumnName + ' = ' + @PKTableSchema + '.' + @PKTableName + '.' + @PKColumnName
                                + ')'
        Fetch Next From @Columns Into @PKTableSchema, @PKTableName, @PKColumnName, @TableSchema, @TableName, @ColumnName
    End
    
    Close @Columns
    Deallocate @Columns
    
    --Print @Sql
    Exec( @Sql )
    

    顺便说一句,我还要提一下,更好的解决方案可能是在您的关系上启用级联删除。使用级联删除,对这个例程的需求将没有实际意义。

    请参阅Cascading Referential Integrity Constraints 了解更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      • 2023-03-25
      • 2019-12-04
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 2019-05-11
      相关资源
      最近更新 更多