回答:
このexists
例で発見したように、SQL Serverは、クエリプランの構築時に外部キーが信頼されているという事実を利用できます。
NOCHECKを使用することで他に失うものはありますか?
Ste Bovによって回答されたはずのない列に値を追加できるという事実とは別に、外部キーが信頼されている場合にクエリプランがより適切になるシナリオが増えます。
以下は、インデックス付きビューの例です。
信頼できるFK制約を持つ2つのテーブルがあります。
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
後で子行を含む行を試みた場合に何が起こるかを明確にできますか?