次のようなテーブルがあります。
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 を持つバッチは次のパスで参照行を解放します。
最初は一時テーブルでこれを行っていましたが、それでも制約に違反しているように見えました。以下は、削除する行を特定するための 2 つの方法 (一時テーブルを使用する方法と、テーブル自体を直接使用する方法) を使用するクエリです。
-- 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
一時テーブル メソッドは余分な不正な行をキャッチしているようで、それが参照整合性チェックに失敗する理由です。生成される行数が異なるのはなぜですか?