【问题标题】:In a SQL database, how do I delete records from Table_B when matching id is already deleted from Table_A?在 SQL 数据库中,当匹配的 id 已从 Table_A 中删除时,如何从 Table_B 中删除记录?
【发布时间】:2015-01-26 16:38:19
【问题描述】:

我有两张桌子Table_ATable_B,其中Table_B.IX_Id = Table_A.IX_ID。这些表中的记录如下所示:

查询:

   select * from Table_A where IX_ID = 4783 
   select * from Table_B where IX_Id = 4783 

结果:

Table_A result

IX_ID       IX_ParentID          IX_CreationDate
----------- -------------------- --------------------
4783        0                    2015-01-26 10:23:00

Table_B result    

IX_Id       Row_Id      Document_Id
----------- ----------- -----------
4783        1           101 
4783        1           99
4783        1           94

现在假设我从Table_A 中删除了一条记录,比我想要的要多4783,还要从Table_B 中删除id 为4783 的记录。

我可以通过以下查询从Table_A 获取已删除的记录:

查询:

;WITH Missing (missnum, maxid)
AS
(
 SELECT 1 AS missnum, (select max(IX_ID) from Table_A)
 UNION ALL
 SELECT missnum + 1, maxid FROM Missing
 WHERE missnum < maxid
)
SELECT missnum
FROM Missing
LEFT OUTER JOIN Table_A missingIds on missingIds.IX_ID = Missing.missnum
WHERE missingIds.IX_ID is NULL  order by 1 desc
OPTION (MAXRECURSION 0);

结果:

missnum
-----------
4783

预期结果:

检查missnum 是否存在于Table_B 中,然后从Table_B 中删除那些匹配的记录,否则不删除。我怎样才能做到这一点?

注意:我从Table_A 删除了很多记录,我正在调整Table_B,其中相应的记录有数百个。

【问题讨论】:

  • 通常你会设置一个带有级联删除的外键,除非你需要更多的控制,此时你会使用删除触发器。这对你来说意味着什么吗?
  • 好吧,我不是 SQL 专业人士,所以我认为我不理解您的建议。截至目前,我只想从 Table_B 中删除那些匹配的 id 记录。抱歉,如果这造成混乱。
  • 您不必是专业人士。如果您正在使用包含关系数据的数据库,则最好有一些由外键强制执行的 REFERENTIAL INTEGRITY。好处之一是您可以使用 CASCADING DELETES 配置外键,这正是您在此处所要求的。如果您搜索每个全部大写的短语,您将很快了解它是如何工作的。重要的东西,除非你学会了,否则会在路上让你头疼(不要搜索那个)。
  • 感谢您的建议。

标签: sql-server tsql


【解决方案1】:

您可以使用NOT IN 来查找与子查询不匹配的内容,这更简单,查询优化器更有机会选择高性能的内容

DELETE FROM Table_B
WHERE IX_Id NOT IN (SELECT IX_Id FROM Table_A)

如果您想让 Table_B 中的 IX_Id 与 Table_A 保持同步,我同意 Will 关于外键的评论

【讨论】:

  • 我想问题是(SELECT IX_Id FROM Table_A) 是否返回与原始递归 CTE 相同的不同 ID 列表。如果是这样,那么这绝对是首选方法,但是我不确定是否确实如此,这就是为什么我发布了更复杂的答案。
  • 问题是描述外键,所以即使CTE漏掉的东西,也应该在这里整理出来。 B 中的 IX_ID 为负数或高于 MAX(Table_A..IX_ID)(如果存在),将被遗漏
【解决方案2】:

拿着这个:

;WITH Missing (missnum, maxid)
AS
(
 SELECT 1 AS missnum, (select max(IX_ID) from Table_A)
 UNION ALL
 SELECT missnum + 1, maxid FROM Missing
 WHERE missnum < maxid
)
SELECT missnum
FROM Missing
LEFT OUTER JOIN Table_A missingIds on missingIds.IX_ID = Missing.missnum
WHERE missingIds.IX_ID is NULL  order by 1 desc
OPTION (MAXRECURSION 0);

把它改成这样:

;WITH Missing (missnum, maxid)
AS
(
 SELECT 1 AS missnum, (select max(IX_ID) from Table_A)
 UNION ALL
 SELECT missnum + 1, maxid FROM Missing
 WHERE missnum < maxid
)
, Missing1 (missnum)
AS
(
 SELECT missnum
 FROM Missing
 LEFT OUTER JOIN Table_A missingIds on missingIds.IX_ID = Missing.missnum
 WHERE missingIds.IX_ID is NULL
)
DELETE FROM Table_B
WHERE IS_Id IN(SELECT missnum FROM Missing1)
OPTION (MAXRECURSION 0);

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多