1

次のようなテーブルがあります。

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

一時テーブル メソッドは余分な不正な行をキャッチしているようで、それが参照整合性チェックに失敗する理由です。生成される行数が異なるのはなぜですか?

4

2 に答える 2

2

(158, 159)最初の方法を使用して非テンプレートを一時テーブルに分離すると、テンプレートは表示されなく(158, 159)なります。しかし、図が示すように、非テンプレートの一部は、一部のテンプレートのみ(158, 159)の親でなければなりませ(158, 159)ん。最初の方法ではそれらを除外しませんが、2 番目の方法では除外します。

最初の方法を引き続き使用できますが、元のセットを左結合の右側として使用する必要があります。または、2 番目の単一クエリ メソッドを使用します。

于 2013-05-11T21:24:59.250 に答える
1

違いは、方法 2 では tnt2 データ セットにテンプレート 158 と 159 がまだ含まれていることです。したがって、これらのテンプレートに属する一部のレコードを tnt1 に結合すると、方法 1 よりも多くのレコードが得られます。これらのテンプレートは結合前に両方のデータ セット (tnt1 と tnt2) から削除されたため、方法 1 ではこれは起こりません。これを方法2のWHERE句に追加してみてくださいAND tnt2.template_id NOT IN ( 158, 159 )

于 2013-05-10T16:41:29.403 に答える