जब मैं `NOCHECK` का उपयोग करके एक विदेशी कुंजी बनाता हूं तो क्या खो जाता है?


11

मुझे पता है कि अगर मैं EXISTS()एक एफके लुकअप वैल्यू पर कॉल करता हूं , तो, अगर वह एफके बाधा पर भरोसा किया जाता है, तो परिणाम तत्काल होता है।

और अगर यह विश्वसनीय नहीं है (जैसे कि जब मैं एफके का उपयोग करके बनाता हूं WITH NOCHECK) तो एसक्यूएल सर्वर को जाकर यह देखना होगा कि क्या वास्तव में मूल्य है या नहीं।

क्या कुछ और है जिसका उपयोग करके मैं हार गया NOCHECK?

जवाबों:


13

जैसा कि आपने अपने existsउदाहरण से पता लगाया है , SQL सर्वर इस तथ्य का उपयोग कर सकता है कि जब क्वेरी योजना बनाई जाती है, तो एक विदेशी कुंजी पर भरोसा किया जाता है।

क्या NOCHECK का उपयोग करके मैं कुछ और खो सकता हूं?

इस तथ्य के अलावा कि आप एक कॉलम में मान जोड़ सकते हैं जो कि Ste Bov द्वारा उत्तर के रूप में नहीं होना चाहिए आपके पास अधिक परिदृश्य होंगे जहां विदेशी कुंजी पर भरोसा करने पर क्वेरी योजना बेहतर होगी।

अनुक्रमित दृश्य के साथ यहां एक उदाहरण है ।

आपके पास एक विश्वसनीय एफके बाधा के साथ दो तालिकाओं हैं।

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 सर्वर जानता है कि इसमें कोई पंक्ति नहीं हो सकती है Cityजो नई पंक्ति से मेल खाएगी Country


4

आप क्वेरी ऑप्टिमाइज़ेशन खो रहे हैं। व्यावहारिक रूप से एकमात्र अनुकूलन जिसे मैं याद करता हूं वह निरर्थक जुड़ावों का उन्मूलन है। उदाहरण के लिए यदि आपके पास एक दृश्य है:

select *
from Orders o
join Customers c on o.CustomerID = c.ID

और जब दृश्य का उपयोग करते हैं तो आप उस कॉलम का उपयोग नहीं करते हैं जो cउचित एफके सेट अप होने पर हटा दिया जा सकता है।

आपका EXISTSउदाहरण एक निरर्थक जुड़ाव को हटाने का एक विशेष मामला है। मुझे नहीं लगता कि विशेष उदाहरण व्यावहारिक रूप से प्रासंगिक है।

आप एक विश्वसनीय बाधा प्रदान करने वाले सख्त डेटा अखंडता को भी खो देते हैं।


3

NOCHECK विकल्प वही करता है जो वह टिन पर कहता है।

यह मुख्य रूप से एक टेबल के अस्तित्व के माध्यम से आधे रास्ते पर एक विदेशी कुंजी जोड़ने के लिए उपयोग किया जाता है जहां एक नया संबंध है जिसकी आवश्यकता नहीं हो सकती है (यह मेरी समझ कम से कम है)।

इसका मतलब यह है कि जिस कॉलम में विदेशी कुंजी एमएई है, उसके भीतर ऐसे मूल्य हैं जो उस निर्धारित मूल्य से संबंधित नहीं हैं जिसे वह संबंधित होना चाहिए।

इसका मतलब यह है कि जब आपके पास SQL ​​सर्वर पर एक NOCHECK विकल्प होता है, तो वास्तव में जाना और जांचना होगा कि क्या कुंजी मूल्य वास्तव में एक प्राथमिक कुंजी है। यदि NOCHECK सेट नहीं है, तो SQL सर्वर मानता है कि उस कॉलम में कुछ भी निश्चित रूप से मौजूद है क्योंकि प्रविष्टि तालिका में मौजूद नहीं हो सकती है यदि यह पहले से ही प्राथमिक कुंजी नहीं थी, और आप पंक्ति को हटाए बिना प्राथमिक कुंजी को हटा नहीं सकते थे। सवाल।

बस NOCHECK एक विदेशी कुंजी है जिसे आप वास्तव में किसी भी चीज़ से संबंधित नहीं कर सकते।

आप वास्तव में विश्वास के अलावा कुछ भी नहीं खो रहे हैं कि प्राथमिक कुंजी होने की गारंटी है।


यह आपके उत्तर से स्पष्ट नहीं है कि बाधा के प्रारंभिक निर्माण के बाद विदेशी कुंजी का कोई प्रवर्तन है या नहीं । क्या आप स्पष्ट कर सकते हैं कि क्या होता है यदि आप INSERTएक नई पंक्ति की कोशिश करते हैं जो एक गैर-मौजूदा मूल पंक्ति से संबंधित है या यदि आप DELETEएक पंक्ति के लिए कोशिश करते हैं जिसमें बाद में बच्चे की पंक्तियाँ हैं?
jpmc26
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.