就仅检查一次关系的单个命令而言(而不是在您的示例中两次 - 一次用于NOT EXISTS
,一次用于DELETE
),那么我希望答案是一个很大的不,抱歉。
(不可行的想法):如果这是一个主要问题,您可以尝试某种引用计数实现,使用触发器来更新计数器 - 但实际上我希望这将比简单地检查更多开销来维护像你一样的钥匙。
您也可以NOCHECK
在删除期间进行调查(因为您自己检查);但是您只能在表级别执行此操作(因此对于管理脚本可能还可以,但对于生产代码则不行)-即:
-- disable
alter table ChildTableName nocheck constraint ForeignKeyName
-- enable
alter table ChildTableName check constraint ForeignKeyName
快速测试表明,启用它后,它会对外键进行额外的聚集索引扫描;禁用它,这将被省略。
这是一个完整的例子;您可以查看这两个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
再一次 - 我强调这应该只从管理脚本之类的东西中运行。