リレーションシップを 1 回だけチェックする単一のコマンドに関しては (この例では 2 回ではなく、 の場合はNOT EXISTS
1 回DELETE
、
(壁のアイデアから外れて):これが大きな問題である場合は、トリガーを使用してカウンターを更新する、ある種の参照カウントの実装を試すことができます-しかし、実際には、これは単にあなたがすでに持っているようなキー。
削除中に調査することもできNOCHECK
ます (自分で確認しているため)。ただし、これはテーブル レベルでのみ実行できます (管理スクリプトではおそらく問題ありませんが、運用コードでは問題ありません)。つまり、次のようになります。
-- disable
alter table ChildTableName nocheck constraint ForeignKeyName
-- enable
alter table ChildTableName check constraint ForeignKeyName
簡単なテストでは、これを有効にすると、外部キーに対して追加のクラスター化インデックス スキャンが実行されることがわかります。無効にすると、これは省略されます。
完全な例を次に示します。2 つの操作のクエリ プランを確認できますDELETE
... (理想的には、残りのコードから分離して):
create table parent (id int primary key)
create table child (id int primary key, pid int)
alter table child add constraint fk_parent foreign key (pid)
references parent (id)
insert parent values (1)
insert parent values (2)
insert child values (1,1)
insert child values (2,1)
-- ******************* THIS ONE CHECKS THE FOREIGN KEY
delete from parent
where not exists (select 1 from child where pid = parent.id)
-- reset
delete from child
delete from parent
insert parent values (1)
insert parent values (2)
insert child values (1,1)
insert child values (2,1)
-- re-run with check disabled
alter table child nocheck constraint fk_parent
-- ******************* THIS ONE DOESN'T CHECK THE FOREIGN KEY
delete from parent
where not exists (select 1 from child where pid = parent.id)
-- re-enable
alter table child check constraint fk_parent
繰り返しますが、これは管理スクリプトなどからのみ実行する必要があることを強調します。