【问题标题】:Delete all associated records删除所有关联记录
【发布时间】:2016-04-27 18:07:57
【问题描述】:

我有一些如下表。

每个表都有一个主键<tablename>_id。不幸的是,即使一个表正在引用另一个表的主键(例如:table2table2_1 正在引用table1.table1_id),其他表上也没有设置外键,并且我不允许更改此设计现在。

根据主键从表中删除记录时,我需要删除所有关联记录。

插图:

如果我在table1 中删除带有table1_id = 10 的记录,我还应该删除其他表中table1_id 是表结构一部分的记录(在这种情况下为table2table2_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

我希望删除后的结果如下:

注意:

  1. 请注意,我知道外键关系在这种情况下会有用,但我现在不能更改表结构/设计(即不能添加外键)。

  2. 我也无法添加触发器。

  3. 我想用 T-SQL / 动态 SQL 达到预期的效果。

  4. 在我的插图中我只使用了 5 个表,但它可以是 n 个类似结构的表。

任何人都可以建议任何替代方法(或自动化),所以我只传递 table1.table1_id,然后它应该删除所有相关记录,好吗?

【问题讨论】:

  • 那里有问题吗?
  • 我认为您可以通过添加一个触发器来解决您的问题,当您从主表中删除关联表时,该触发器将删除关联表上的记录。但我不确定您的具体问题。
  • @TomH :更新了问题,谢谢。
  • @NWest 更新了问题,我无法添加触发器。谢谢
  • 存储过程呢?具有单个参数(初始 id)的存储过程可以为您完成这项工作。

标签: sql sql-server-2008 sql-server-2012


【解决方案1】:

解决这个问题的标准方法是使用外键/触发器,但一旦你不能使用它们,你就必须以不同的方式保持完整性:

所以,您需要存储过程来执行以下操作:

delete from table1 where table1_id = ####;
delete from table2 where table1_id not in (select table1_id from table1);
delete from table2_1 where table1_id not in (select table1_id from table1);
delete from table3 where table2_id not in (select table2_id from table2);
delete from table4 where table3_id not in (select table3_id from table3);
delete from table5 where table4_id not in (select table4_id from table4);

这将从 table1 中删除行,然后从其他表中删除所有“无效”行

【讨论】:

    【解决方案2】:

    如果允许存储过程,类似这样:

    CREATE PROC delrec @id int AS
    BEGIN
     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=@id)))
     DELETE table4 where table3_id in 
      (select table3_id from table3 where table2_id in 
        (select table2_id from table2 where table1_id=@id))
     DELETE table3 where table2_id in 
      (select table2_id from table2 where table1_id=@id)
     DELETE table2 where table1_id=@id
     DELETE table2_1 where table1_id=@id
     DELETE table1 where table1_id=@id
    END
    

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 2013-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 2015-06-25
      • 1970-01-01
      相关资源
      最近更新 更多