我有一张这样的桌子:
CREATE TABLE navigation_trees (
id INT NOT NULL PRIMARY KEY,
parent_id INT NULL,
template_id NOT NULL
)
因为有一个外键,parent_id 引用同一个表的 id,所以试图删除另一行的 parent_id 引用的行违反了参照完整性。SQL Server 将不允许 ON DELETE CASCADE 因为循环引用级联的(明显)潜力。
因此,我正在尝试删除具有除 ( 158, 159 ) 之外的模板 ID 的所有行。为了做到这一点,我试图选择所有不是引用目标的行(即没有其他行的 parent_id 是该行的 id),删除它们,然后在循环中重复该过程直到没有更多删除。每次删除批次时,任何具有 parent_id 的批次都将在下一次通过时释放参考行。
最初我是用临时表来做这个的,但它似乎仍然违反了约束。这是一个使用两种方法(使用临时表和直接在表本身上)尝试识别要删除的行的查询:
-- method one: temp table for filtering template IDs
SELECT id, parent_id
INTO #navTrees
FROM navigation_trees
WHERE template_id NOT IN ( 158, 159 )
SELECT DISTINCT tnt1.id
INTO #set1
FROM #navTrees AS tnt1
LEFT OUTER JOIN #navTrees AS tnt2 ON tnt1.id = tnt2.parent_id
WHERE tnt2.parent_id IS NULL
-- method two: filtering template IDs directly in the join
SELECT DISTINCT tnt1.id
INTO #set2
FROM navigation_trees AS tnt1
LEFT OUTER JOIN navigation_trees AS tnt2 ON tnt1.id = tnt2.parent_id
WHERE tnt2.parent_id IS NULL
AND tnt1.template_id NOT IN ( 158, 159 )
SELECT COUNT(*)
FROM #set1
-- Produces: 106023
SELECT COUNT(*)
FROM #set2
-- Produces: 102575
DROP TABLE #navTrees
DROP TABLE #set1
DROP TABLE #set2
临时表方法似乎捕获了额外的错误行,这就是它未能通过引用完整性检查的原因。为什么它们产生不同数量的行?