重新启用外键约束后执行计划奇怪

dan*_*die 5 sql t-sql sql-server sql-execution-plan

我有一个奇怪的问题,在设置nocheck外部约束并重新启用它之后,

我得到了与nocheckon 一起使用的同样过时的执行计划.

为什么SQL服务器会生成执行计划,就好像外部约束FKBtoA被禁用,即使再次使用以下语句添加检查?

alter table B check constraint FKBtoA
Run Code Online (Sandbox Code Playgroud)

[UPDATE1]
到目前为止,删除外部约束并读取它有效.

alter table B drop constraint FKBtoA
alter table B add constraint FKBtoA foreign key (AID) references A(ID)
Run Code Online (Sandbox Code Playgroud)

但对于真正的大桌子来说,这似乎是一种矫枉过正 - 有更好的方法吗?

[回答]

我不得不WITH CHECK在下面添加alter语句来获取旧的执行计划

alter table B WITH CHECK add constraint FKBtoA foreign key (AID) references A(ID)
Run Code Online (Sandbox Code Playgroud)

这是一个完整的SQL语句

create table A ( ID int identity primary key )
create table B ( 
    ID int identity primary key,
    AID int not null constraint FKBtoA references A (ID)
)

select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)

alter table B nocheck constraint FKBtoA
GO
select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)

alter table B check constraint FKBtoA
GO
select  *
from    B
where   exists (select 1 from A where A.ID = B.AID)
Run Code Online (Sandbox Code Playgroud)

以下是每个SELECT语句的执行计划的屏幕截图

在禁用外键约束之前
替代文字

禁用外键约束后
替代文字

重新启用外键约束后
替代文字

A-K*_*A-K 7

很可能您的约束已启用但不受信任,因此子表中可能存在孤立行.阅读Hugo Kornelis的这篇精彩文章:你能相信你的约束吗?