【发布时间】:2016-04-27 18:07:57
【问题描述】:
我有一些如下表。
每个表都有一个主键<tablename>_id。不幸的是,即使一个表正在引用另一个表的主键(例如:table2、table2_1 正在引用table1.table1_id),其他表上也没有设置外键,并且我不允许更改此设计现在。
根据主键从表中删除记录时,我需要删除所有关联记录。
插图:
如果我在table1 中删除带有table1_id = 10 的记录,我还应该删除其他表中table1_id 是表结构一部分的记录(在这种情况下为table2 和table2_1)。当table2中的一条记录被删除时,我也应该删除其他表中table2_id是表结构一部分的记录(本例为table3),我需要遍历直到没有依赖并删除所有相关记录。
我尝试生成如下查询(假设我想删除 table1_is=10 的记录):
CREATE TABLE table1 (table1_id INT IDENTITY(10, 1), table1_field1 varchar(100), table1_field2 BIT);
CREATE TABLE table2 (table2_id INT IDENTITY(100, 1), table2_field1 varchar(100), table2_field2 BIT, table1_id INT);
CREATE TABLE table2_1 (table2_1_id INT IDENTITY(500, 1), table2_1_field1 varchar(100), table2_1_field2 BIT, table1_id INT);
CREATE TABLE table3 (table3_id INT IDENTITY(1000, 1), table3_field1 varchar(100), table3_field2 BIT, table2_id INT);
CREATE TABLE table4 (table4_id INT IDENTITY(10000, 1), table4_field1 varchar(100), table4_field2 BIT, table3_id INT);
CREATE TABLE table5 (table5_id INT IDENTITY(100000, 1), table5_field1 varchar(100), table5_field2 BIT, table4_id INT);
INSERT INTO table1(table1_field1, table1_field2) VALUES ('table1_field1_1', 0), ('table1_field1_2', 1), ('table1_field1_3', 0), ('table1_field1_4', 1);
INSERT INTO table2(table2_field1, table2_field2, table1_id) VALUES ('table2_field1_1', 0, 10), ('table2_field1_2', 1, 11), ('table2_field1_3', 0, 12), ('table2_field1_4', 1, 13);
INSERT INTO table2_1(table2_1_field1, table2_1_field2, table1_id) VALUES ('table2_1_field1_1', 0, 10), ('table2_1_field1_2', 1, 11), ('table2_1_field1_3', 0, 12), ('table2_1_field1_4', 1, 13);
INSERT INTO table3(table3_field1, table3_field2, table2_id) VALUES ('table3_field1_1', 0, 100), ('table3_field1_2', 1, 101), ('table3_field1_3', 0, 102), ('table3_field1_4', 1, 103);
INSERT INTO table4(table4_field1, table4_field2, table3_id) VALUES ('table4_field1_1', 0, 1000), ('table4_field1_2', 1, 1001), ('table4_field1_3', 0, 1002), ('table4_field1_4', 1, 1003);
INSERT INTO table5(table5_field1, table5_field2, table4_id) VALUES ('table5_field1_1', 0, 10000), ('table5_field1_2', 1, 10001), ('table5_field1_3', 0, 10002), ('table5_field1_4', 1, 10003);
SELECT * FROM table1
SELECT * FROM table2
SELECT * FROM table2_1
SELECT * FROM table3
SELECT * FROM table4
SELECT * FROM table5
select t.name, c.name, 'DELETE [' + t.name + '] WHERE [' + c.name + '] = 10',
'SELECT t.name [tn], c.name [cn] FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name=''' + t.name + '_id'' and t.name<>''' + t.name + ''' '
from sys.tables t
inner join sys.columns c on t.object_id=c.object_id
where c.name='table1_id' and t.name<>'table1'
order by t.name
/* Use the SELECT queries to find other dependencies like below */
SELECT t.name [t], c.name [c],'SELECT t.name [tn], c.name [cn] FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name=''' + t.name + '_id'' and t.name<>''' + t.name + ''''
FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name='table2_id' and t.name<>'table2'
SELECT t.name [tn], c.name [cn], 'SELECT t.name [tn], c.name [cn] FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name=''' + t.name + '_id'' and t.name<>''' + t.name + ''''
FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name='table3_id' and t.name<>'table3'
SELECT t.name [tn], c.name [cn], 'SELECT t.name [tn], c.name [cn] FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name=''' + t.name + '_id'' and t.name<>''' + t.name + ''''
FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name='table4_id' and t.name<>'table4'
SELECT t.name [tn], c.name [cn] FROM sys.tables t inner join sys.columns c on t.object_id=c.object_id where c.name='table5_id' and t.name<>'table5'
/* I need to run the SQL queries something like below */
DELETE table5 where table4_id in (select table4_id from table4 where table3_id in (select table3_id from table3 where table2_id in (select table2_id from table2 where table1_id=10)))
DELETE table4 where table3_id in (select table3_id from table3 where table2_id in (select table2_id from table2 where table1_id=10))
DELETE table3 where table2_id in (select table2_id from table2 where table1_id=10)
DELETE table2 where table1_id=10
DELETE table2_1 where table1_id=10
DELETE table1 where table1_id=10
我希望删除后的结果如下:
注意:
-
请注意,我知道外键关系在这种情况下会有用,但我现在不能更改表结构/设计(即不能添加外键)。
我也无法添加触发器。
我想用 T-SQL / 动态 SQL 达到预期的效果。
在我的插图中我只使用了 5 个表,但它可以是 n 个类似结构的表。
任何人都可以建议任何替代方法(或自动化),所以我只传递 table1.table1_id,然后它应该删除所有相关记录,好吗?
【问题讨论】:
-
那里有问题吗?
-
我认为您可以通过添加一个触发器来解决您的问题,当您从主表中删除关联表时,该触发器将删除关联表上的记录。但我不确定您的具体问题。
-
@TomH :更新了问题,谢谢。
-
@NWest 更新了问题,我无法添加触发器。谢谢
-
存储过程呢?具有单个参数(初始 id)的存储过程可以为您完成这项工作。
标签: sql sql-server-2008 sql-server-2012