3 つ以上のテーブルで内部結合を使用して、テーブルからレコードを削除したいと考えています。Aのpkが他のすべての言及されたテーブルで共有されているテーブルA、B、C、Dがあるとします。次に、条件がこれら 2 つのテーブルからフェッチされるため、テーブル B と A の内部結合を使用して、テーブル D からレコードを削除する削除クエリを作成する方法を説明します。DB2 の観点からこのクエリが必要です。制限があるため、IN 句または EXISTS は使用していません。
3 に答える
あなたの説明から、スキーマは次のようになります。
A(pk_A, col1, col2, ...)
B(pk_B, fk_A, col1, col2, ..., 外部キー fk_A は A(pk_A) を参照)
C(pk_c, fk_A, col1, col2, ..., 外部キー fk_A は A(pk_A) を参照)
D(pk_d, fk_A, col1, col2, ..., 外部キー fk_A 参照 A(pk_A))
あなたが言うように、IN句が使用されている場合、DB2は1000行しか削除できません。DB2 についてはわかりませんが、Oracle では IN 句内で 1000 個の手動値しか許可されていません。少なくとも Oracle では、サブクエリの結果にそのような制限はありません。EXISTS は、Oracle や DB2 を含むすべてのデータベースが行の存在のみをチェックするため、問題にはなりません。
テーブル D からデータを削除するには、次の 3 つのシナリオがあります。
fk_A が (自然に) 列 A.pk_A を使用してテーブル A のレコードを参照しているテーブル D からデータを削除したいとします。
DELETE FROM d WHERE EXISTS ( SELECT 1 FROM a WHERE a.pk_A = d.fk_A );
fk_A がテーブル A のレコードを参照し、テーブル A のそのレコードが列 B.fk_A によっても参照されているテーブル D からデータを削除したいとします。A にあるが B にはないデータを D から削除したくありません。次のように記述できます。
DELETE FROM d WHERE EXISTS ( SELECT 1 FROM a INNER JOIN b ON a.pk_A = b.fk_A WHERE a.pk_A = d.fk_A );
3 番目のシナリオは、テーブル A のレコードを参照するテーブル D のデータを削除する必要があり、A のそのレコードは列 B.fk_A とテーブル C.fk_A によっても参照される場合です。A、B、C、D の 4 つのテーブルすべてに共通するデータのみをテーブル D から削除します。次のように記述できます。
DELETE FROM d WHERE EXISTS ( SELECT 1 FROM a INNER JOIN b ON a.pk_A = b.fk_A INNER JOIN c ON a.pk_A = c.fk_A WHERE a.pk_A = d.fk_A );
要件に応じて、これらのクエリのいずれかを組み込むことができます。
サブクエリが複数の行を取得する場合、「=」演算子はエラーを返すことに注意してください。また、DB2 が ANY または ALL キーワードをサポートしているかどうかもわかりません。そのため、IN、ANY、および ALL よりも高速に実行されるシンプルだが強力な EXISTS キーワードを使用しました。
また、ここでは、EXISTS 句内のサブクエリが「SELECT a.pk」やその他の列ではなく、「SELECT 1」を使用していることがわかります。これは、どのデータベースでも、EXISTS が行の存在のみを検索し、列内の特定の値を検索しないためです。
delete from D
where fk = (select d.fk from D d,A a,B b where a.pk = b.fk and b.fk = d.fk )
これはうまくいくはずです