Як ви виявили на своєму 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
.
INSERT
новий рядок, який стосується неіснуючого батьківського рядка, або якщо ви спробуєтеDELETE
пізніше рядок, який має дочірні рядки?