Sql 从没有相关数据的表中删除-其中不在,并且连接失败
考虑下表结构: 我正在创建一个存储过程,它将从Sql 从没有相关数据的表中删除-其中不在,并且连接失败,sql,sql-server,join,where,sql-delete,Sql,Sql Server,Join,Where,Sql Delete,考虑下表结构: 我正在创建一个存储过程,它将从RelatedA和RelatedB中删除数据。之后,我想从主数据中删除所有在中不再有关联的RelatedA和RelatedB中的内容 我尝试了3种不同的查询来获取要删除的ID 使用简单的WHERE 在WHERE 使用join+在ON 所有这些都不会返回任何记录进行删除,而且我确信有几个原因是我刚刚在主数据中插入了新记录(并且没有在相关表中插入数据的触发器) 我实际上有两个问题: 我做错了什么? 我的问题之间的确切区别是什么?(奖金) 您只需对父查询
RelatedA
和RelatedB
中删除数据。之后,我想从主数据中删除所有在中不再有关联的RelatedA
和RelatedB
中的内容
我尝试了3种不同的查询来获取要删除的ID
使用简单的WHERE
在WHERE
使用join+在ON
所有这些都不会返回任何记录进行删除,而且我确信有几个原因是我刚刚在主数据
中插入了新记录(并且没有在相关表中插入数据的触发器)
我实际上有两个问题:
我做错了什么?
我的问题之间的确切区别是什么?(奖金)
您只需对父查询执行而不在中。因此,从这个开始,它应该为您提供两个相关表中都没有匹配项的所有记录。这是您的第一个查询所做的
SELECT *
FROM MasterData
WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
然后将其更改为删除:
DELETE MasterData
FROM MasterData
WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
并用一些实际值进行测试:
--Create tables
DECLARE @MasterData TABLE (ID BIGINT)
DECLARE @RelatedA TABLE (ID BIGINT, MasterDataID BIGINT)
DECLARE @RelatedB TABLE (ID BIGINT, MasterDataID BIGINT)
--Some test data
INSERT INTO @MasterData VALUES (1),(2),(3),(4),(5)
INSERT INTO @RelatedA VALUES (1,1),(2,2)
INSERT INTO @RelatedB VALUES (1,3),(2,4)
SELECT * FROM @MasterData --5 rows
--Do the delete
DELETE @MasterData
FROM @MasterData MD
WHERE MD.ID NOT IN (SELECT MasterDataID FROM @RelatedA)
AND MD.ID NOT IN (SELECT MasterDataID FROM @RelatedB)
SELECT * FROM @MasterData --4 rows
您只需对父查询执行而不在中。因此,从这个开始,它应该为您提供两个相关表中都没有匹配项的所有记录。这是您的第一个查询所做的
SELECT *
FROM MasterData
WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
然后将其更改为删除:
DELETE MasterData
FROM MasterData
WHERE ID NOT IN (SELECT MasterDataID FROM RelatedA)
AND ID NOT IN (SELECT MasterDataID FROM RelatedB)
并用一些实际值进行测试:
--Create tables
DECLARE @MasterData TABLE (ID BIGINT)
DECLARE @RelatedA TABLE (ID BIGINT, MasterDataID BIGINT)
DECLARE @RelatedB TABLE (ID BIGINT, MasterDataID BIGINT)
--Some test data
INSERT INTO @MasterData VALUES (1),(2),(3),(4),(5)
INSERT INTO @RelatedA VALUES (1,1),(2,2)
INSERT INTO @RelatedB VALUES (1,3),(2,4)
SELECT * FROM @MasterData --5 rows
--Do the delete
DELETE @MasterData
FROM @MasterData MD
WHERE MD.ID NOT IN (SELECT MasterDataID FROM @RelatedA)
AND MD.ID NOT IN (SELECT MasterDataID FROM @RelatedB)
SELECT * FROM @MasterData --4 rows
第一个应该有效。第二个缺少“左联接”,它将与不存在的行不匹配:
SELECT MD.ID
FROM MasterData MD
LEFT JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
LEFT JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
WHERE RelA.MasterDataID IS NULL
AND RelB.MasterDataID IS NULL
第一个应该有效。第二个缺少“左联接”,它将与不存在的行不匹配:
SELECT MD.ID
FROM MasterData MD
LEFT JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
LEFT JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
WHERE RelA.MasterDataID IS NULL
AND RelB.MasterDataID IS NULL
首先让我们看看那些不起作用的
DELETE FROM MasterData
WHERE ID IN (
SELECT MD.ID
FROM MasterData MD
JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
WHERE RelA.MasterDataID IS NULL
AND RelB.MasterDataID IS NULL
)
WHERE
条件永远不会为真,因为您正在进行内部联接而不是左联接
联接条件永远不会为true,因为null
不等于null
(即null
=null
返回null
而不是true),第二部分要求MasterDataID
为null
这包括一个不必要的子查询,但除非我遗漏了一些东西,否则它应该可以工作。您可以将子查询重写为(同样,您也可以在上面的前两个查询中省略子查询)
就我个人而言,我宁愿不存在
DELETE FROM MasterData MD
WHERE NOT EXISTS (SELECT 1 FROM RelatedA WHERE MasterDataID = MD.ID)
AND NOT EXISTS (SELECT 1 FROM RelatedB WHERE MasterDataID = MD.ID)
首先让我们看看那些不起作用的
DELETE FROM MasterData
WHERE ID IN (
SELECT MD.ID
FROM MasterData MD
JOIN RelatedA RelA on RelA.MasterDataID = MD.ID
JOIN RelatedB RelB on RelB.MasterDataID = MD.ID
WHERE RelA.MasterDataID IS NULL
AND RelB.MasterDataID IS NULL
)
WHERE
条件永远不会为真,因为您正在进行内部联接而不是左联接
联接条件永远不会为true,因为null
不等于null
(即null
=null
返回null
而不是true),第二部分要求MasterDataID
为null
这包括一个不必要的子查询,但除非我遗漏了一些东西,否则它应该可以工作。您可以将子查询重写为(同样,您也可以在上面的前两个查询中省略子查询)
就我个人而言,我宁愿不存在
DELETE FROM MasterData MD
WHERE NOT EXISTS (SELECT 1 FROM RelatedA WHERE MasterDataID = MD.ID)
AND NOT EXISTS (SELECT 1 FROM RelatedB WHERE MasterDataID = MD.ID)
我建议使用notexists
select
md.*
from MasterData md
where not exists (
select 1 from RelatedA A where md.id = A.MasterDataID)
and not exists (
select 1 from RelatedB B where md.id = B.MasterDataID)
;
将这些数据一起使用(如上所示)或单独使用以评估数据。如果满足此条件,它将很容易转换为删除查询
我建议使用不存在
select
md.*
from MasterData md
where not exists (
select 1 from RelatedA A where md.id = A.MasterDataID)
and not exists (
select 1 from RelatedB B where md.id = B.MasterDataID)
;
将这些数据一起使用(如上所示)或单独使用以评估数据。如果满足此条件,它将很容易转换为删除查询
如果运行子查询,子查询是否返回数据?(即,SELECT…
bit)@DavidG我的意思是,就我的问题而言,我目前正在测试这些。更新了我的问题以更好地反映这一点。请尝试在SQL Fiddle、jsut中复制这一点,用于WHERE。。不在
示例中。它应该可以工作。非常确定第一个应该可以工作。如果运行子查询,子查询会返回数据吗?(即,SELECT…
bit)@DavidG我的意思是,就我的问题而言,我目前正在测试这些。更新了我的问题以更好地反映这一点。请尝试在SQL Fiddle、jsut中复制这一点,用于WHERE。。不在
示例中。应该行得通。第一个肯定行得通。是不是我的数据库严重堵塞了?我现在正在用一个表测试您的第二个两个查询,当我使用where not in
时,我没有记录,而使用where not exists
时,我得到所有记录。到底发生了什么事?@MDeSchaepmeester不确定,不在
和不存在
查询应该返回相同的数据只有不存在
目前似乎有效。我不能用不在中正确地获得它,我做的和你做的完全一样。如果这被证明是数据库的完整性问题,我不会感到惊讶,因为它在几年前投入使用后,实际上没有得到维护……对于大型子查询来说,“不存在”通常更快,所以可能“不存在”只是需要很长时间?奇怪的是查询“成功执行”在大约3秒钟内,而它应该需要更多的时间(这里谈论的是成百上千条记录)。可能是某个查询优化器的“bug”?可能是我的数据库严重堵塞了吗?我现在正在用一个表测试您的第二个两个查询,当我使用where not in
时,我没有记录,而使用where not exists
时,我得到所有记录。到底发生了什么事?@MDeSchaepmeester不确定,不在
和不存在
查询应该返回相同的数据只有不存在
目前似乎有效。我不能用不在中正确地获得它,我做的和你做的完全一样。如果这被证明是数据库的完整性问题,我不会感到惊讶,因为它在几年前投入使用后,实际上没有得到维护……对于大型子查询,“不存在”通常更快,所以“不存在”可能只是需要很长时间?奇怪的是