強制されない参照制約環境内のデータを操作するときには、常に注意が必要です。 強制されない参照制約を使用して参照のリレーションシップを定義する場合に、DMLリクエストに冗長なRI結合が含まれており、除去された結合のPK-FK行の対が一致しない場合、INSERT、DELETE、およびUPDATE文により、親テーブル内のデータの参照リレーションシップが破壊される可能性があります。 RI結合は、PK=FKという仮定に基づいて除去され、無効な結果がSELECT結果内に返されるか、データベースに正しくない更新が行なわれます。
例えば、子テーブルcol_2内のtable_2と親テーブルcol_1内のtable_1との間の参照制約によって関連付けられた以下の2つのテーブルがあるとします。
CREATE TABLE table_1 ( col_1 INTEGER NOT NULL, col_2 INTEGER UNIQUE PRIMARY INDEX (col_1)); CREATE TABLE table_2 ( col_1 INTEGER, col_2 INTEGER, FOREIGN KEY (col_2) REFERENCES WITH NO CHECK OPTION table_1(col_1));
いくつかの行をtable_1およびtable_2に挿入します。 値が入ったテーブルは、以下のようになると想定します。
table_1 | table_2 | |||
---|---|---|---|---|
PK | FK | |||
col_1 | col_2 | col_1 | col_2 | |
1 | 2 | 5 | 6 | |
2 | 2 | 6 | 7 | |
3 | 2 | 7 | 8 |
テーブル間で定義された参照の関係は、col_2内のtable_2のそれぞれの値がcol_1のtable_1内の同一の値に対応している必要があることを示しています。
システムは、この関係に参照整合性を遂行しないように指示されるため、対になっていないtable_2.col_2値は、その関係で定義された制約に違反する場合でさえ挿入を受け入れられます。 この時点で、参照整合性エラーが示されていますが、同じく重要なのは、さらなるデータ破壊の前提条件が設定されているということです。
以下のUPDATE文を使用してtable_2を更新するとします。
UPDATE table_2 SET col_1=1 WHERE table_1.col_1=table_2.col_2;
table_2.col_2はtable_1.col_1 WITH NO CHECK OPTIONを参照するため、この更新により、table_1.col_1 = table_2.col_2結合が除去されます。このようにして、指定されたWHERE句による条件フィルタが無視され、テーブルtable_2内のすべての行のcol_1値が1になるように誤って更新され、データベースが破壊されます。