2013-05-01 6 views
9

मेरे पास दो टेबल, बिक्री और उत्पाद हैं। बिक्री में एक विदेशी कुंजी बाधा उत्पाद संदर्भ है। विदेशी कुंजी WITH NOCHECK बनाया गया था और सृजन के बाद तुरंत अक्षम कर दिया गया था। मैं विदेशी कुंजी बाधा को सक्षम और भरोसा करना चाहता हूं। इसे सक्षम करने में काम करता है लेकिन मैं इसे भरोसा नहीं कर सकता।विदेशी कुंजी बाधाओं को कैसे विश्वसनीय बनाया जाए?

StackOverflow और विभिन्न ब्लॉगों पर इसी तरह के सवालों के संकेत मिलता है कि चल ALTER TABLE T WITH CHECK CHECK CONSTRAINT Cis_disabled=0 और is_not_trusted=0 में परिणाम चाहिए, लेकिन is_not_trusted मेरे लिए हमेशा 1 है। मैं क्या गलत कर रहा हूं?

मैं एसक्यूएल फिडल पर नमूना कोड डालने की कोशिश की, लेकिन यह "बी सी सी" आदेशों पसंद नहीं था, इसलिए यहाँ यह है:

-- "_Scratch" is just a sandbox DB that I use for testing stuff. 
USE _Scratch 

CREATE TABLE dbo.Product 
(
    ProductKeyId INT PRIMARY KEY NOT NULL, 
    Description VARCHAR(40) NOT NULL 
) 

CREATE TABLE dbo.Sale 
(
    ProductKeyId INT NOT NULL, 
    SaleTime DATETIME NOT NULL, 
    Value MONEY NOT NULL 
) 

ALTER TABLE dbo.Sale WITH NOCHECK 
    ADD CONSTRAINT FK_Product_ProductKeyId FOREIGN KEY (ProductKeyId) 
    REFERENCES dbo.Product (ProductKeyId) NOT FOR REPLICATION; 

ALTER TABLE dbo.Sale NOCHECK CONSTRAINT FK_Product_ProductKeyId 

INSERT INTO dbo.Product VALUES (1, 'Food') 
INSERT INTO dbo.Sale VALUES (1, GETDATE(), 1.00) 

-- Check the disabled/trusted state 
SELECT name, is_disabled, is_not_trusted 
FROM sys.foreign_keys 
WHERE name = 'FK_Product_ProductKeyId' 

    -- name      is_disabled is_not_trusted 
    -- FK_Product_ProductKeyId 1   1 

-- Check the FK_Product_ProductKeyId constraint 
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId') 

    -- DBCC execution completed. 
    -- If DBCC printed error messages, contact your system administrator. 

-- Check all constraints on Sale table 
DBCC CHECKCONSTRAINTS('Sale') 

    -- DBCC execution completed. 
    -- If DBCC printed error messages, contact your system administrator. 

-- Add the constraint and check existing data 
ALTER TABLE Sale WITH CHECK CHECK CONSTRAINT FK_Product_ProductKeyId 

-- Check the disabled/trusted state 
SELECT name, is_disabled, is_not_trusted 
FROM sys.foreign_keys 
WHERE name = 'FK_Product_ProductKeyId' 

    -- name      is_disabled is_not_trusted 
    -- FK_Product_ProductKeyId 0   1 

-- Check the FK_Product_ProductKeyId constraint 
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId') 

    -- DBCC execution completed. 
    -- If DBCC printed error messages, contact your system administrator. 

-- Check all constraints on Sale table 
DBCC CHECKCONSTRAINTS('Sale') 

    -- DBCC execution completed. 
    -- If DBCC printed error messages, contact your system administrator. 

उत्तर

17

अपने उदाहरण के आधार पर, मैं भी कोशिश की है:

  • विदेशी कुंजी को छोड़ें और फिर से बनाएं।
  • तालिका को छोड़ें और फिर से बनाएं।

    NOT FOR REPLICATION 
    

    ऐसा लगता है कि अगर एक बाधा नहीं प्रतिकृति के लिए के साथ बनाई गई है, यह हमेशा विश्वसनीय नहीं है:

तब मैं आदेश में कुछ देखा।

Books Online से हवाला देते हुए:

कुछ मामलों में, यह एक प्रतिकृति टोपोलॉजी में उपयोगकर्ता गतिविधि के लिए वांछनीय एजेंट गतिविधि से अलग माना जा रहा है। उदाहरण के लिए, यदि प्रकाशक पर किसी उपयोगकर्ता द्वारा कोई पंक्ति डाली जाती है और तालिका में चेक बाधा को पूरा करती है, तो उसे की आवश्यकता नहीं हो सकती है जब एक प्रतिकृति एजेंट द्वारा पंक्ति डाली जाती है तो उसी बाधा को लागू करें सब्सक्राइबर। प्रतिकृति विकल्प के लिए नहीं निर्दिष्ट करें कि निम्नलिखित डाटाबेस वस्तुओं को अलग व्यवहार किया जाता जब एक प्रतिकृति एजेंट एक कार्रवाई निष्पादित करने की अनुमति देता:

विदेशी कुंजी की कमी

विदेशी कुंजी बाधा लागू नहीं किया जाता है जब एक प्रतिकृति एजेंट ऑपरेशन डालें, अपडेट करें या हटाएं।

ऐसा लगता है कि IS_NOT_TRUSTED सेटिंग की तरह केवल प्रतिकृति से प्रभावित के लिए प्रासंगिक है। मुझे लगता है कि जब तक आप जिस सर्वर पर काम कर रहे हैं उस पर बाधा लागू होती है, तो यह ठीक होना चाहिए। तो मैं आगे चला गया और इस बात की पुष्टि:

SELECT name, is_disabled, is_not_trusted 
FROM sys.foreign_keys 
WHERE name = 'FK_Product_ProductKeyId' 

name     is_disabled is_not_trusted 
FK_Product_ProductKeyId 0   1 

INSERT INTO dbo.Sale VALUES (2, GETDATE(), 1.00) 

Msg 547, Level 16, State 0, Line 1 
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Product_ProductKeyId". The conflict occurred in database "_Scratch", table "dbo.Product", column 'ProductKeyId'. 
The statement has been terminated. 

आप अभी भी मन की शांति के लिए IS_NOT_TRUSTED = 0 को देखने के लिए, बस NOT FOR REPLICATION बिना विदेशी कुंजी को पुनः चाहते हैं।

यदि आप में से वे सोच रहे हैं, तो मैंने जांच बाधाओं पर भी वही प्रभाव सत्यापित किया है।

+0

लुई, परीक्षण करने के लिए समय निकालने के लिए धन्यवाद, यह एक अच्छा जवाब है, काश मैं आपको एक से अधिक अपवर्त दे सकता हूं :) मैं बाधाओं को भरोसा करने की कोशिश कर रहा था क्योंकि मैंने कहीं पढ़ा है कि गैर-भरोसेमंद लोग कुछ प्रश्नों के प्रदर्शन को प्रभावित कर सकते हैं। मैंने डेटाबेस को विरासत में मिला है और हम दोहराना नहीं चाहते हैं लेकिन सबकुछ "प्रतिकृति के लिए नहीं" लगता है, जो "सट्टा सामान्यता" का मामला हो सकता है। – WileCau

+0

@WileCau आपको वास्तव में निष्पादन समय में सुधार मिलता है जब एफके को विश्वसनीय नहीं माना जाता है। मैं इस अभ्यास को प्रोत्साहित नहीं कर रहा हूं। हालांकि, स्क्वायर एसक्यूएल से उत्पादन एसक्यूएल कहने से, बड़ी मात्रा में डेटा को स्थानांतरित करना बहुत उपयोगी है। अधिक जानकारी के लिए यहां देखें http://sqlblog.com/blogs/hugo_kornelis/archive/2007/03/29/can-you-trust-your-constraints.aspx – harsimranb

+0

@ Pathachiever11, आप सही हैं, बाधाओं को अक्षम करने का कारण ऐसा इसलिए था क्योंकि कुछ तालिकाओं को शुरू में एक अन्य ज्ञात संगत डेटाबेस से पॉप्युलेट किया गया था, इसलिए उन्होंने डेटा माइग्रेशन को धीमा कर दिया। प्रारंभिक प्रवासन के बाद बाधाओं को नए डेटा पर स्थिरता लागू करने के लिए फिर से सक्षम किया जाना चाहिए था, लेकिन वे भूल गए थे। – WileCau

संबंधित मुद्दे