SQL Serverでは、列に複数の外部キーを作成できます。異なる名前を使用するたびに、同じオブジェクトを参照する別のキーを作成できます。基本的に、すべてのキーは同じ関係を定義しています。同じ列に定義され、別のテーブルの同じ列を参照する複数の外部キーを使用することについて教えてください。 SQL Serverがそのようなことを可能にすることの利点は何ですか?
名前のみが異なる冗長な制約を設定してもメリットはありません。同様に、名前だけが異なる冗長なインデックスを作成してもメリットはありません。どちらも価値のないオーバーヘッドを追加します。
SQL Serverデータベースエンジンは、そうすることを妨げません。優れた制約ネーミング制約ネーミング規則(FK_ReferencingTable_ReferencedTableなど)は、そのようなミスから1つを保護するのに役立ちます。
SQL Serverでは、多くの愚かなことができます。
列に外部キーを作成することもできます それ自体を参照 -すべての行がそれ自体の制約を満たすため、違反されることは決してないという事実にもかかわらず。
同じ関係に2つの外部キーを作成する機能が役立つ可能性があるEdgeケースの1つは、外部キーの検証に使用されるインデックスが作成時に決定されるためです。より良い(つまり、より狭い)インデックスが後で発生した場合、これにより、新しい外部キー制約がより良いインデックスにバインドされて作成され、元の制約はアクティブな制約のないギャップなしで削除されます。
(以下の例のように)
CREATE TABLE T1(
T1_Id INT PRIMARY KEY CLUSTERED NOT NULL,
Filler CHAR(4000) NULL,
)
INSERT INTO T1 VALUES (1, '');
CREATE TABLE T2(
T2_Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
T1_Id INT NOT NULL CONSTRAINT FK REFERENCES T1 (T1_Id),
Filler CHAR(4000) NULL,
)
ALTER TABLE T1 ADD CONSTRAINT
UQ_T1 UNIQUE NONCLUSTERED(T1_Id)
/*Execution Plan uses clustered index*/
INSERT INTO T2 VALUES (1,1)
ALTER TABLE T2 WITH CHECK ADD CONSTRAINT FK2 FOREIGN KEY(T1_Id)
REFERENCES T1 (T1_Id)
ALTER TABLE T2 DROP CONSTRAINT FK
/*Now Execution Plan now uses non clustered index*/
INSERT INTO T2 VALUES (1,1)
DROP TABLE T2, T1;
一時的な制約として、両方の制約が存在する間は、すべての挿入が両方のインデックスに対して検証されます。
同じ外部キー制約を使用することはできません。つまり、同じ列にあり、同じテーブルと列を参照します。
同じチェックを2回以上繰り返すようなものです。
同じ列に50個のインデックスを作成し、2番目のログファイルを追加し、最大サーバーメモリを20MBに設定できるのと同じ理由です。ほとんどの人はこれらのことを行わないでしょうが、たまに行う正当な理由があるため、エンジンにオーバーヘッドを作成して、単に不適切なことしか行われていないものに対するチェックを追加することでメリットが得られます。
青緑色のように聞こえます。
青から緑に切り替わり始めたら、一時的に追加のコピーを作成する必要があります。
私たちがしたいことは、追加の外部キーを一時的に作成することですCHECK WITH NOCHECK
およびON UPDATE CASCADE ON DELETE SET NULL
;これが行うことは、機能する外部キーですが、キーの作成時に既存の行はチェックされません。
後で一致するはずのすべての行をクリーンアップした後、コマンドオプションなしで新しい外部キーを作成します(デフォルトはCHECK WITH CHECK
これは通常必要なものです)、一時的な外部キーを削除します。
外部キーを削除して再作成した場合、一部のガベージ行がスリップする可能性があることに注意してください。