Database
 sql >> डेटाबेस >  >> RDS >> Database

विदेशी कुंजी, अवरोधन, और अद्यतन विरोध

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

इस लेख में एक ऐसे विचार को शामिल किया गया है जिसे अधिक प्रचार नहीं मिलता है:अवरुद्ध करना . को कम करने के लिए , आपको उन विदेशी कुंजी संबंधों के मूल पक्ष पर विशिष्टता को लागू करने के लिए उपयोग किए जाने वाले अनुक्रमितों के बारे में ध्यान से सोचना चाहिए।

यह लागू होता है कि आप लॉकिंग . का उपयोग कर रहे हैं या नहीं प्रतिबद्ध पढ़ें या संस्करण-आधारित प्रतिबद्ध स्नैपशॉट अलगाव (आरसीएसआई) पढ़ें। जब SQL सर्वर इंजन द्वारा विदेशी कुंजी संबंधों की जाँच की जाती है, तो दोनों ब्लॉकिंग का अनुभव कर सकते हैं।

स्नैपशॉट अलगाव (एसआई) के तहत, एक अतिरिक्त चेतावनी है। वही आवश्यक समस्या अनपेक्षित (और यकीनन अतार्किक) लेनदेन विफलताओं का कारण बन सकती है स्पष्ट अद्यतन विरोधों के कारण।

यह लेख दो भागों में है। पहला भाग लॉकिंग कमिटेड और रीड कमिटेड स्नैपशॉट आइसोलेशन के तहत फॉरेन की ब्लॉकिंग को देखता है। दूसरा भाग स्नैपशॉट अलगाव के अंतर्गत संबंधित अद्यतन विरोधों को कवर करता है।

1. विदेशी कुंजी जांचों को अवरुद्ध करना

आइए पहले देखें कि विदेशी कुंजी जांच के कारण अवरोध होने पर इंडेक्स डिज़ाइन कैसे प्रभावित हो सकता है।

निम्न डेमो पढ़ें प्रतिबद्ध के अंतर्गत चलाया जाना चाहिए एकांत। SQL सर्वर के लिए डिफ़ॉल्ट लॉकिंग प्रतिबद्ध है; Azure SQL डेटाबेस डिफ़ॉल्ट के रूप में RCSI का उपयोग करता है। बेझिझक आप जो चाहें चुनें, या प्रत्येक सेटिंग के लिए एक बार स्क्रिप्ट चलाएँ ताकि आप स्वयं सत्यापित कर सकें कि व्यवहार समान है।

-- Use locking read committed
ALTER DATABASE CURRENT
    SET READ_COMMITTED_SNAPSHOT OFF;
 
-- Or use row-versioning read committed
ALTER DATABASE CURRENT
    SET READ_COMMITTED_SNAPSHOT ON;

एक विदेशी कुंजी संबंध से जुड़ी दो तालिकाएँ बनाएँ:

CREATE TABLE dbo.Parent
(
    ParentID integer NOT NULL,
    ParentNaturalKey varchar(10) NOT NULL,
    ParentValue integer NOT NULL,
 
    CONSTRAINT [PK dbo.Parent ParentID]
        PRIMARY KEY (ParentID),
 
    CONSTRAINT [AK dbo.Parent ParentNaturalKey]
        UNIQUE (ParentNaturalKey)
);
 
CREATE TABLE dbo.Child 
(
    ChildID integer NOT NULL,
    ChildNaturalKey varchar(10) NOT NULL,
    ChildValue integer NOT NULL,
    ParentID integer NULL,
 
    CONSTRAINT [PK dbo.Child ChildID]
        PRIMARY KEY (ChildID),
 
    CONSTRAINT [AK dbo.Child ChildNaturalKey]
        UNIQUE (ChildNaturalKey),
 
    CONSTRAINT [FK dbo.Child to dbo.Parent]
        FOREIGN KEY (ParentID)
            REFERENCES dbo.Parent (ParentID)
);

पैरेंट टेबल में एक पंक्ति जोड़ें:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
 
DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 100;
 
INSERT dbo.Parent 
(
    ParentID, 
    ParentNaturalKey, 
    ParentValue
) 
VALUES 
(
    @ParentID, 
    @ParentNaturalKey, 
    @ParentValue
);

दूसरे कनेक्शन . पर , गैर-कुंजी पैरेंट तालिका विशेषता को अपडेट करें ParentValue लेन-देन के अंदर, लेकिन प्रतिबद्ध न करें यह अभी तक:

DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 200;
 
BEGIN TRANSACTION;
    UPDATE dbo.Parent 
    SET ParentValue = @ParentValue 
    WHERE ParentID = @ParentID;

यदि आप चाहें तो प्राकृतिक कुंजी का उपयोग करके अद्यतन विधेय को लिखने के लिए स्वतंत्र महसूस करें, इससे हमारे वर्तमान उद्देश्यों के लिए कोई फर्क नहीं पड़ता है।

पहले कनेक्शन पर वापस जाएं , चाइल्ड रिकॉर्ड जोड़ने का प्रयास करें:

DECLARE
    @ChildID integer = 101,
    @ChildNaturalKey varchar(10) = 'CNK1',
    @ChildValue integer = 999,
    @ParentID integer = 1;
 
INSERT dbo.Child 
(
    ChildID, 
    ChildNaturalKey,
    ChildValue, 
    ParentID
) 
VALUES 
(
    @ChildID, 
    @ChildNaturalKey,
    @ChildValue, 
    @ParentID    
);

यह सम्मिलन कथन अवरुद्ध . करेगा , चाहे आपने लॉक करना या संस्करण बनाना chose चुना हो प्रतिबद्ध पढ़ें इस परीक्षण के लिए अलगाव।

स्पष्टीकरण

चाइल्ड रिकॉर्ड डालने के लिए निष्पादन योजना है:

चाइल्ड टेबल में नई पंक्ति डालने के बाद, निष्पादन योजना विदेशी कुंजी बाधा की जाँच करती है। यदि सम्मिलित पैरेंट आईडी शून्य है (बाएं सेमी जॉइन पर 'पास थ्रू' विधेय के माध्यम से प्राप्त किया गया) तो चेक को छोड़ दिया जाता है। वर्तमान मामले में, जोड़ा गया मूल आईडी शून्य नहीं है, इसलिए विदेशी कुंजी जांच है प्रदर्शन किया।

SQL सर्वर पैरेंट तालिका में एक मेल खाने वाली पंक्ति की तलाश करके विदेशी कुंजी बाधा की पुष्टि करता है। इंजन पंक्ति-संस्करण का उपयोग नहीं कर सकता ऐसा करने के लिए — यह सुनिश्चित होना चाहिए कि वह जिस डेटा की जाँच कर रहा है वह नवीनतम प्रतिबद्ध डेटा . है , कुछ पुराने संस्करण नहीं। इंजन एक आंतरिक READCOMMITTEDLOCK . जोड़कर इसे सुनिश्चित करता है पैरेंट टेबल पर विदेशी कुंजी की जाँच करने के लिए तालिका संकेत।

अंतिम परिणाम यह है कि SQL सर्वर पैरेंट तालिका में संबंधित पंक्ति पर एक साझा लॉक प्राप्त करने का प्रयास करता है, जो ब्लॉक है क्योंकि दूसरे सत्र में अभी तक अप्रतिबद्ध अद्यतन के कारण असंगत अनन्य-मोड लॉक है।

स्पष्ट होने के लिए, आंतरिक लॉकिंग संकेत केवल विदेशी कुंजी जांच पर लागू होता है। योजना के शेष भाग में अभी भी RCSI का उपयोग किया जाता है, यदि आपने रीड कमिटेड आइसोलेशन स्तर के उस कार्यान्वयन को चुना है।

ब्लॉकिंग से बचना

दूसरे सत्र में खुले लेनदेन को कमिट या रोलबैक करें, फिर परीक्षण वातावरण को रीसेट करें:

DROP TABLE IF EXISTS
    dbo.Child, dbo.Parent;

परीक्षण तालिकाएं फिर से बनाएं, लेकिन इस बार डिफ़ॉल्ट स्वीकार करने के बजाय, हम प्राथमिक कुंजी को गैर-संकुल बनाना चुनते हैं और अद्वितीय बाधा संकुलित:

CREATE TABLE dbo.Parent
(
    ParentID integer NOT NULL,
    ParentNaturalKey varchar(10) NOT NULL,
    ParentValue integer NOT NULL,
 
    CONSTRAINT [PK dbo.Parent ParentID]
        PRIMARY KEY NONCLUSTERED (ParentID),
 
    CONSTRAINT [AK dbo.Parent ParentNaturalKey]
        UNIQUE CLUSTERED (ParentNaturalKey)
);
 
CREATE TABLE dbo.Child 
(
    ChildID integer NOT NULL,
    ChildNaturalKey varchar(10) NOT NULL,
    ChildValue integer NOT NULL,
    ParentID integer NULL,
 
    CONSTRAINT [PK dbo.Child ChildID]
        PRIMARY KEY NONCLUSTERED (ChildID),
 
    CONSTRAINT [AK dbo.Child ChildNaturalKey]
        UNIQUE CLUSTERED (ChildNaturalKey),
 
    CONSTRAINT [FK dbo.Child to dbo.Parent]
        FOREIGN KEY (ParentID)
            REFERENCES dbo.Parent (ParentID)
);

पैरेंट टेबल में पहले की तरह एक पंक्ति जोड़ें:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
 
DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 100;
 
INSERT dbo.Parent 
(
    ParentID, 
    ParentNaturalKey, 
    ParentValue
) 
VALUES 
(
    @ParentID, 
    @ParentNaturalKey, 
    @ParentValue
);

दूसरे सत्र . में , अद्यतन को फिर से किए बिना चलाएँ। मैं इस बार प्राकृतिक कुंजी का उपयोग केवल विविधता के लिए कर रहा हूं - यह परिणाम के लिए महत्वपूर्ण नहीं है। यदि आप चाहें तो फिर से सरोगेट कुंजी का उपयोग करें।

DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 200;
 
BEGIN TRANSACTION 
    UPDATE dbo.Parent 
    SET ParentValue = @ParentValue 
    WHERE ParentNaturalKey = @ParentNaturalKey;

अब चाइल्ड इंसर्ट को पहले सत्र . पर वापस चलाएँ :

DECLARE
    @ChildID integer = 101,
    @ChildNaturalKey varchar(10) = 'CNK1',
    @ChildValue integer = 999,
    @ParentID integer = 1;
 
INSERT dbo.Child 
(
    ChildID, 
    ChildNaturalKey,
    ChildValue, 
    ParentID
) 
VALUES 
(
    @ChildID, 
    @ChildNaturalKey,
    @ChildValue, 
    @ParentID    
);

इस बार चाइल्ड इंसर्ट अवरुद्ध नहीं होता . यह सच है कि क्या आप लॉकिंग के तहत चल रहे हैं- या संस्करण-आधारित पढ़ने के लिए प्रतिबद्ध अलगाव। यह कोई टाइपो या त्रुटि नहीं है:RCSI को यहां कोई फर्क नहीं पड़ता।

स्पष्टीकरण

चाइल्ड रिकॉर्ड इंसर्ट की निष्पादन योजना इस बार थोड़ी अलग है:

सब कुछ पहले जैसा ही है (अदृश्य READCOMMITTEDLOCK . सहित) संकेत) सिवाय विदेशी कुंजी जांच अब गैर-संकुल . का उपयोग करती है मूल तालिका प्राथमिक कुंजी को लागू करने वाला अद्वितीय सूचकांक। पहले टेस्ट में इस इंडेक्स को क्लस्टर किया गया था।

तो हम इस बार ब्लॉक क्यों नहीं करते?

दूसरे सत्र में अभी तक अप्रतिबद्ध पैरेंट टेबल अपडेट में एक अनन्य लॉक . है संकुल अनुक्रमणिका . पर पंक्ति क्योंकि आधार तालिका को संशोधित किया जा रहा है। ParentValue . में परिवर्तन कॉलम नहीं . करता है ParentID . पर गैर-संकुल प्राथमिक कुंजी को प्रभावित करें , ताकि गैर-संकुल अनुक्रमणिका की पंक्ति लॉक न हो

इसलिए विदेशी कुंजी जांच बिना किसी विवाद के गैर-संकुल प्राथमिक कुंजी इंडेक्स पर आवश्यक साझा लॉक प्राप्त कर सकती है, और चाइल्ड टेबल इंसर्ट तुरंत सफल होता है

जब प्राथमिक को क्लस्टर किया गया था, तो विदेशी कुंजी चेक को उसी संसाधन (क्लस्टर इंडेक्स पंक्ति) पर एक साझा लॉक की आवश्यकता थी जो विशेष रूप से अपडेट स्टेटमेंट द्वारा लॉक किया गया था।

व्यवहार आश्चर्यजनक हो सकता है, लेकिन यह बग नहीं है . विदेशी कुंजी को अपनी अनुकूलित एक्सेस विधि की जांच करने से तार्किक रूप से अनावश्यक लॉक विवाद से बचा जाता है। विदेशी कुंजी लुकअप को अवरुद्ध करने की कोई आवश्यकता नहीं है क्योंकि ParentID विशेषता समवर्ती अद्यतन से प्रभावित नहीं होती है।

2. परिहार्य अद्यतन विरोध

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

हालांकि एसआई का उपयोग करते समय एक महत्वपूर्ण संभावित अंतर है। रीड कमिटेड (लॉकिंग या RCSI) आइसोलेशन के तहत, चाइल्ड रो इंसर्ट आखिरकार सफल होता है दूसरे सत्र में अद्यतन के बाद या वापस रोल करता है। SI का उपयोग करने से लेन-देन का जोखिम होता है निरस्त एक स्पष्ट अद्यतन विरोध के कारण।

यह प्रदर्शित करने के लिए थोड़ा मुश्किल है क्योंकि स्नैपशॉट लेनदेन BEGIN TRANSACTION से शुरू नहीं होता है कथन - यह उस बिंदु के बाद पहले उपयोगकर्ता डेटा एक्सेस के साथ शुरू होता है।

निम्नलिखित स्क्रिप्ट एसआई प्रदर्शन को सेट करती है, एक अतिरिक्त डमी टेबल के साथ जिसका उपयोग केवल यह सुनिश्चित करने के लिए किया जाता है कि स्नैपशॉट लेनदेन वास्तव में शुरू हो गया है। यह परीक्षण भिन्नता का उपयोग करता है जहां संदर्भित प्राथमिक कुंजी को एक अद्वितीय क्लस्टर . का उपयोग करके लागू किया जाता है अनुक्रमणिका (डिफ़ॉल्ट):

ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON;
GO
DROP TABLE IF EXISTS
    dbo.Dummy, dbo.Child, dbo.Parent;
GO
CREATE TABLE dbo.Dummy
(
    x integer NULL
);
 
CREATE TABLE dbo.Parent
(
    ParentID integer NOT NULL,
    ParentNaturalKey varchar(10) NOT NULL,
    ParentValue integer NOT NULL,
 
    CONSTRAINT [PK dbo.Parent ParentID]
        PRIMARY KEY (ParentID),
 
    CONSTRAINT [AK dbo.Parent ParentNaturalKey]
        UNIQUE (ParentNaturalKey)
);
 
CREATE TABLE dbo.Child 
(
    ChildID integer NOT NULL,
    ChildNaturalKey varchar(10) NOT NULL,
    ChildValue integer NOT NULL,
    ParentID integer NULL,
 
    CONSTRAINT [PK dbo.Child ChildID]
        PRIMARY KEY (ChildID),
 
    CONSTRAINT [AK dbo.Child ChildNaturalKey]
        UNIQUE (ChildNaturalKey),
 
    CONSTRAINT [FK dbo.Child to dbo.Parent]
        FOREIGN KEY (ParentID)
            REFERENCES dbo.Parent (ParentID)
);

मूल पंक्ति सम्मिलित करना:

DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 100;
 
INSERT dbo.Parent 
(
    ParentID, 
    ParentNaturalKey, 
    ParentValue
) 
VALUES 
(
    @ParentID, 
    @ParentNaturalKey, 
    @ParentValue
);

अभी भी पहले सत्र में है , स्नैपशॉट लेनदेन शुरू करें:

-- Session 1
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRANSACTION;
 
-- Ensure snapshot transaction is started
SELECT COUNT_BIG(*) FROM dbo.Dummy AS D;

दूसरे सत्र . में (किसी भी अलगाव स्तर पर चल रहा है):

-- Session 2
DECLARE
    @ParentID integer = 1,
    @ParentNaturalKey varchar(10) = 'PNK1',
    @ParentValue integer = 200;
 
BEGIN TRANSACTION;
    UPDATE dbo.Parent 
    SET ParentValue = @ParentValue 
    WHERE ParentID = @ParentID;

पहले सत्र में चाइल्ड पंक्ति सम्मिलित करने का प्रयास अवरुद्ध उम्मीद के मुताबिक:

-- Session 1
DECLARE
    @ChildID integer = 101,
    @ChildNaturalKey varchar(10) = 'CNK1',
    @ChildValue integer = 999,
    @ParentID integer = 1;
 
INSERT dbo.Child 
(
    ChildID, 
    ChildNaturalKey,
    ChildValue, 
    ParentID
) 
VALUES 
(
    @ChildID, 
    @ChildNaturalKey,
    @ChildValue, 
    @ParentID    
);

अंतर तब होता है जब हम लेन-देन समाप्त करते हैं दूसरे सत्र में। अगर हम इसे वापस रोल करें , पहले सत्र की चाइल्ड पंक्ति प्रविष्टि सफलतापूर्वक पूर्ण

अगर हम इसके बजाय प्रतिबद्ध खुला लेनदेन:

-- Session 2
COMMIT TRANSACTION;

पहला सत्र अद्यतन विरोध की रिपोर्ट करता है और वापस आ जाता है:

स्पष्टीकरण

यह अद्यतन विरोध इस तथ्य के बावजूद होता है कि विदेशी कुंजी सत्यापित किया जा रहा था बदला नहीं गया दूसरे सत्र के अपडेट द्वारा।

कारण अनिवार्य रूप से परीक्षणों के पहले सेट के समान ही है। जब संकुल अनुक्रमणिका संदर्भित कुंजी प्रवर्तन के लिए उपयोग किया जाता है, स्नैपशॉट लेनदेन का सामना एक पंक्ति से होता है जिसे शुरू होने के बाद से संशोधित किया गया है। स्नैपशॉट अलगाव के तहत इसकी अनुमति नहीं है।

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

ऐसी कई अन्य परिस्थितियाँ हैं जहाँ स्नैपशॉट अलगाव अनपेक्षित अद्यतन विरोधों, या अन्य त्रुटियों की रिपोर्ट कर सकता है। उदाहरण के लिए मेरा पिछला लेख देखें।

निष्कर्ष

पंक्ति-भंडार तालिका के लिए संकुल अनुक्रमणिका का चयन करते समय ध्यान में रखने के लिए कई विचार हैं। यहां वर्णित मुद्दे केवल एक अन्य कारक हैं मूल्यांकन करने के लिए।

यह विशेष रूप से सच है यदि आप स्नैपशॉट अलगाव का उपयोग करेंगे। कोई भी निरस्त लेन-देन का आनंद नहीं लेता है , विशेष रूप से एक जो यकीनन अतार्किक है। यदि आप RCSI का उपयोग कर रहे हैं, तो पढ़ते समय अवरोधित करना विदेशी कुंजियों की पुष्टि करना अनपेक्षित हो सकता है, और गतिरोध पैदा कर सकता है।

डिफ़ॉल्ट PRIMARY KEY . के लिए इसकी सहायक अनुक्रमणिका को संकुलित . के रूप में बनाने के लिए बाधा है , जब तक कि तालिका परिभाषा में कोई अन्य अनुक्रमणिका या बाधा इसके बजाय क्लस्टर किए जाने के बारे में स्पष्ट न हो। स्पष्ट होना एक अच्छी आदत है आपके डिजाइन के इरादे के बारे में, इसलिए मैं आपको CLUSTERED . लिखने के लिए प्रोत्साहित करूंगा या NONCLUSTERED हर बार।

डुप्लीकेट इंडेक्स?

ऐसे समय हो सकते हैं जब आप गंभीरता से विचार करते हैं, ठोस कारणों से, एक ही कुंजी (कुंजी) के साथ एक संकुल अनुक्रमणिका और गैर-संकुल अनुक्रमणिका होने पर ।

इरादा संकुल . के माध्यम से उपयोगकर्ता प्रश्नों के लिए इष्टतम पठन पहुंच प्रदान करना हो सकता है इंडेक्स (कुंजी लुकअप से परहेज), जबकि कॉम्पैक्ट गैर-क्लस्टर किए गए के माध्यम से विदेशी कुंजी के लिए न्यूनतम-अवरुद्ध (और अद्यतन-विरोधी) सत्यापन को भी सक्षम करता है। इंडेक्स जैसा कि यहां दिखाया गया है।

यह हासिल किया जा सकता है, लेकिन कुछ स्नैग . हैं देखने के लिए:

  1. एक से अधिक उपयुक्त लक्ष्य अनुक्रमणिका को देखते हुए, SQL सर्वर गारंटी . के लिए कोई तरीका प्रदान नहीं करता है विदेशी कुंजी प्रवर्तन के लिए कौन सी अनुक्रमणिका का उपयोग किया जाएगा।

    डैन गुज़मैन ने सीक्रेट ऑफ़ फॉरेन की इंडेक्स बाइंडिंग में अपनी टिप्पणियों का दस्तावेजीकरण किया, लेकिन ये अधूरे हो सकते हैं, और किसी भी मामले में अनिर्दिष्ट हैं, और इसलिए बदल सकते हैं

    आप केवल एक लक्ष्य . को सुनिश्चित करके इस पर काम कर सकते हैं विदेशी कुंजी बनाते समय सूचकांक, लेकिन यह चीजों को जटिल करता है, और भविष्य के मुद्दों को आमंत्रित करता है यदि विदेशी कुंजी बाधा को कभी भी हटा दिया जाता है और फिर से बनाया जाता है।

  2. यदि आप शॉर्टहैंड विदेशी कुंजी सिंटैक्स का उपयोग करते हैं, तो SQL सर्वर केवल बाधा को प्राथमिक कुंजी से बांधें , चाहे वह असंकुल हो या संकुलित।

निम्नलिखित कोड स्निपेट बाद के अंतर को दर्शाता है:

CREATE TABLE dbo.Parent
(
    ParentID integer NOT NULL UNIQUE CLUSTERED
);
 
-- Shorthand (implicit) syntax
-- Fails with error 1773
CREATE TABLE dbo.Child
(
    ChildID integer NOT NULL PRIMARY KEY NONCLUSTERED,
    ParentID integer NOT NULL 
        REFERENCES dbo.Parent
);
 
-- Explicit syntax succeeds
CREATE TABLE dbo.Child
(
    ChildID integer NOT NULL PRIMARY KEY NONCLUSTERED,
    ParentID integer NOT NULL 
        REFERENCES dbo.Parent (ParentID)
);

लोग आरसीएसआई और एसआई के तहत बड़े पैमाने पर पढ़ने-लिखने के टकराव को नजरअंदाज करने के आदी हो गए हैं। उम्मीद है कि इस लेख ने आपको विदेशी कुंजी से संबंधित तालिकाओं के लिए भौतिक डिज़ाइन को लागू करने के बारे में सोचने के लिए कुछ अतिरिक्त दिया है।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. सिंक्रोनस सांख्यिकी अपडेट को ट्रैक करना

  2. टी-एसक्यूएल में वर्तमान तिथि और समय (समय क्षेत्र के बिना) कैसे प्राप्त करें

  3. समानांतर योजनाएँ कैसे शुरू होती हैं - भाग 3

  4. SQL VARCHAR डेटा प्रकार तेज़ डेटाबेस के लिए क्या करें और क्या न करें

  5. 0 से 60 :अप्रत्यक्ष चौकियों पर स्विच करना