我需要获取存储过程(不是标准,只有自定义)来删除未使用的行表(table1)和其他一些表(table2,table3,table4 ......- 我们不知道有多少个表引用to table1 by FOREIGN KEY CONSTRAINT )可以引用此表。
例如:
С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
答案 0 :(得分: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 )
不过,我还要提一下,更好的解决方案可能是在您的关系中启用Cascade Delete。通过级联删除,对此例程的需求没有实际意义。