Answers:
正如您在exists
示例中发现的那样,SQL Server可以使用以下事实:构建查询计划时,外键是可信的。
使用NOCHECK还有什么我丢掉的东西吗?
除了您可以将值添加到不应由Ste Bov回答的那一列的事实之外,您还会遇到更多方案,当信任外键时,查询计划会更好。
这是一个带有索引视图的示例。
您有两个表具有受信任的FK约束。
create table dbo.Country
(
CountryID int primary key,
Name varchar(50) not null
);
create table dbo.City
(
CityID int identity primary key,
Name varchar(50),
IsBig bit not null,
CountryID int not null
);
alter table dbo.City
add constraint FK_CountryID
foreign key (CountryID)
references dbo.Country(CountryID);
没有多少国家,但是有无数城市,其中一些是大城市。
样本数据:
-- Three countries
insert into dbo.Country(CountryID, Name) values
(1, 'Sweden'),
(2, 'Norway'),
(3, 'Denmark');
-- Five big cities
insert into dbo.City(Name, IsBig, CountryID) values
('Stockholm', 1, 1),
('Gothenburg', 1, 1),
('Malmoe', 1, 1),
('Oslo', 1, 2),
('Copenhagen', 1, 3);
-- 300 small cities
insert into dbo.City(Name, IsBig, CountryID)
select 'NoName', 0, Country.CountryID
from dbo.Country
cross apply (
select top(100) *
from sys.columns
) as T;
此应用程序中最常执行的查询与查找每个国家/地区的大城市数量有关。为了加快处理速度,我们添加了索引视图。
create view dbo.BigCityCount with schemabinding
as
select count_big(*) as BigCityCount,
City.CountryID,
Country.Name as CountryName
from dbo.City
inner join dbo.Country
on City.CountryID = Country.CountryID
where City.IsBig = 1
group by City.CountryID,
Country.Name;
go
create unique clustered index CX_BigCityCount
on dbo.BigCityCount(CountryID);
过了一会儿就需要增加一个新国家
insert into dbo.Country(CountryID, Name) values(4, 'Finland');
该插入的查询计划没有任何意外。
聚集索引插入到Country
表中。
现在,如果您的外键不受信任
alter table dbo.City nocheck constraint FK_CountryID;
然后您添加一个新国家
insert into dbo.Country(CountryID, Name) values(5, 'Iceland');
您最终会得到一张不太漂亮的图片。
下部分支在那里更新索引视图。它会进行全表扫描,City
以确定表中是否CountryID = 5
已存在行的国家/地区City
。
当密钥被信任时,SQL Server知道其中没有行City
与中的新行匹配Country
。
NOCHECK选项的作用与锡盒上所说的完全相同。
它主要用于在存在表的途中添加外键,在表中可能不需要新的关系(至少是我的理解)。
这意味着具有外键的列中的值可能与应与其指定的值不相关。
这意味着当您在SQL Server上具有NOCHECK选项时,必须实际检查该键值是否实际上是主键。如果未设置NOCHECK,则SQL Server假定该列中的任何内容都肯定存在,因为如果该表项尚不是主键,则该表中将不存在该项,并且您不能删除该主键而不删除其中的行。题。
简而言之,NOCHECK是一个外键,您无法信任它实际上与任何事物相关联。
除了主键保证在那里存在的信任之外,您实际上并没有失去任何其他东西。
INSERT
不存在的父行相关的新行,或者以后尝试DELETE
具有子行的行会发生什么情况?