web-dev-qa-db-ja.com

SQL Serverの同じ列での複数の外部キーの使用

SQL Serverでは、列に複数の外部キーを作成できます。異なる名前を使用するたびに、同じオブジェクトを参照する別のキーを作成できます。基本的に、すべてのキーは同じ関係を定義しています。同じ列に定義され、別のテーブルの同じ列を参照する複数の外部キーを使用することについて教えてください。 SQL Serverがそのようなことを可能にすることの利点は何ですか?

enter image description here

10
igelr

名前のみが異なる冗長な制約を設定してもメリットはありません。同様に、名前だけが異なる冗長なインデックスを作成してもメリットはありません。どちらも価値のないオーバーヘッドを追加します。

SQL Serverデータベースエンジンは、そうすることを妨げません。優れた制約ネーミング制約ネーミング規則(FK_ReferencingTable_ReferencedTableなど)は、そのようなミスから1つを保護するのに役立ちます。

12
Dan Guzman

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;

一時的な制約として、両方の制約が存在する間は、すべての挿入が両方のインデックスに対して検証されます。

17
Martin Smith

同じ外部キー制約を使用することはできません。つまり、同じ列にあり、同じテーブルと列を参照します。

同じチェックを2回以上繰り返すようなものです。

13
ypercubeᵀᴹ

同じ列に50個のインデックスを作成し、2番目のログファイルを追加し、最大サーバーメモリを20MBに設定できるのと同じ理由です。ほとんどの人はこれらのことを行わないでしょうが、たまに行う正当な理由があるため、エンジンにオーバーヘッドを作成して、単に不適切なことしか行われていないものに対するチェックを追加することでメリットが得られます。

6
Aaron Bertrand

青緑色のように聞こえます。

青から緑に切り替わり始めたら、一時的に追加のコピーを作成する必要があります。

私たちがしたいことは、追加の外部キーを一時的に作成することですCHECK WITH NOCHECKおよびON UPDATE CASCADE ON DELETE SET NULL;これが行うことは、機能する外部キーですが、キーの作成時に既存の行はチェックされません。

後で一致するはずのすべての行をクリーンアップした後、コマンドオプションなしで新しい外部キーを作成します(デフォルトはCHECK WITH CHECKこれは通常必要なものです)、一時的な外部キーを削除します。

外部キーを削除して再作成した場合、一部のガベージ行がスリップする可能性があることに注意してください。

2
Joshua