प्राथमिक कुंजी मान क्यों बदलेगा?


18

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

मेरी समझ हमेशा से रही है कि एक प्राथमिक कुंजी अपरिवर्तनीय होनी चाहिए, और इस उत्तर को पढ़ने के बाद से मेरी खोज ने केवल उत्तर प्रदान किए हैं जो एक सर्वोत्तम अभ्यास के रूप में दर्शाते हैं।

रिकॉर्ड बनने के बाद प्राथमिक कुंजी मूल्य को किन परिस्थितियों में बदलना होगा?


7
जब एक प्राथमिक कुंजी चुना जाता है जो अपरिवर्तनीय नहीं है?
15 अक्टूबर को ypercube y

2
नीचे दिए गए सभी उत्तरों के लिए अभी तक एक मामूली नाइट। प्राथमिक कुंजी में एक मूल्य बदलना तब तक बड़ी बात नहीं है जब तक कि प्राथमिक कुंजी भी क्लस्टर इंडेक्स न हो जाए। यह केवल तभी मायने रखता है जब क्लस्टर इंडेक्स के मान बदल जाते हैं।
केनेथ फिशर

6
@ केनेथफिशर या यदि इसे एक (या कई) एफके द्वारा संदर्भित किया जाता है तो अन्य या एक ही तालिका में और एक परिवर्तन को कई, (संभवतः लाखों या अरबों) पंक्तियों में कैस्केड किया जाना है।
ypercube y

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

3
सभी वास्तविक दुनिया मूल्य बदल सकते हैं (विभिन्न कारणों से)। यह सरोगेट / सिंथेटिक कुंजी के लिए मूल प्रेरणाओं में से एक था: कृत्रिम मूल्यों को उत्पन्न करने में सक्षम होने के लिए जिन्हें कभी नहीं बदलने के लिए भरोसा किया जा सकता था।
RBarryYoung

जवाबों:


24

यदि आप किसी व्यक्ति के नाम को प्राथमिक कुंजी के रूप में उपयोग कर रहे हैं और उनका नाम बदल गया है तो आपको प्राथमिक कुंजी को बदलने की आवश्यकता होगी। इसका ON UPDATE CASCADEउपयोग तब से किया जाता है क्योंकि यह अनिवार्य रूप से उन सभी संबंधित तालिकाओं में परिवर्तन को रोक देता है जिनके प्राथमिक कुंजी के लिए विदेशी-कुंजी संबंध हैं।

उदाहरण के लिए:

USE tempdb;
GO

CREATE TABLE dbo.People
(
    PersonKey VARCHAR(200) NOT NULL
        CONSTRAINT PK_People
        PRIMARY KEY CLUSTERED
    , BirthDate DATE NULL
) ON [PRIMARY];

CREATE TABLE dbo.PeopleAKA
(
    PersonAKAKey VARCHAR(200) NOT NULL
        CONSTRAINT PK_PeopleAKA
        PRIMARY KEY CLUSTERED
    , PersonKey VARCHAR(200) NOT NULL
        CONSTRAINT FK_PeopleAKA_People
        FOREIGN KEY REFERENCES dbo.People(PersonKey)
        ON UPDATE CASCADE
) ON [PRIMARY];

INSERT INTO dbo.People(PersonKey, BirthDate)
VALUES ('Joe Black', '1776-01-01');

INSERT INTO dbo.PeopleAKA(PersonAKAKey, PersonKey)
VALUES ('Death', 'Joe Black');

एक SELECTदोनों तालिकाओं के खिलाफ:

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;

यह दिखाता है:

यहाँ छवि विवरण दर्ज करें

यदि हम PersonKeyकॉलम अपडेट करते हैं , और SELECT:

UPDATE dbo.People
SET PersonKey = 'Mr Joe Black'
WHERE PersonKey = 'Joe Black';

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonKey = pa.PersonKey;

हम देखते हैं:

यहाँ छवि विवरण दर्ज करें

उपर्युक्त UPDATEकथन की योजना को देखते हुए, हम स्पष्ट रूप से देखते हैं कि दोनों सारणियों को एक एकल अद्यतन वक्तव्य द्वारा विदेशी कुंजी के रूप में परिभाषित किया गया है ON UPDATE CASCADE:

यहाँ छवि विवरण दर्ज करें इसे और अधिक स्पष्टता में देखने के लिए ऊपर दी गई छवि पर क्लिक करें

अंत में, हम अपनी अस्थायी तालिकाओं की सफाई करेंगे:

DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;

सरोगेट कुंजियों का उपयोग करते हुए ऐसा करने का पसंदीदा 1 तरीका होगा:

USE tempdb;
GO

CREATE TABLE dbo.People
(
    PersonID INT NOT NULL IDENTITY(1,1)
        CONSTRAINT PK_People
        PRIMARY KEY CLUSTERED
    , PersonName VARCHAR(200) NOT NULL
    , BirthDate DATE NULL
) ON [PRIMARY];

CREATE TABLE dbo.PeopleAKA
(
    PersonAKAID INT NOT NULL IDENTITY(1,1)
        CONSTRAINT PK_PeopleAKA
        PRIMARY KEY CLUSTERED
    , PersonAKAName VARCHAR(200) NOT NULL
    , PersonID INT NOT NULL
        CONSTRAINT FK_PeopleAKA_People
        FOREIGN KEY REFERENCES dbo.People(PersonID)
        ON UPDATE CASCADE
) ON [PRIMARY];

INSERT INTO dbo.People(PersonName, BirthDate)
VALUES ('Joe Black', '1776-01-01');

INSERT INTO dbo.PeopleAKA(PersonID, PersonAKAName)
VALUES (1, 'Death');

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;

UPDATE dbo.People
SET PersonName = 'Mr Joe Black'
WHERE PersonID = 1;

पूर्णता के लिए, अपडेट स्टेटमेंट की योजना बहुत सरल है, और कुंजियों को सरोगेट करने के लिए एक फायदा दिखाता है, अर्थात् केवल एक पंक्ति को प्राकृतिक-कुंजी परिदृश्य में कुंजी वाले प्रत्येक पंक्ति के विपरीत अपडेट करने की आवश्यकता होती है:

यहाँ छवि विवरण दर्ज करें

SELECT *
FROM dbo.People p
    INNER JOIN dbo.PeopleAKA pa ON p.PersonID = pa.PersonID;

DROP TABLE dbo.PeopleAKA;
DROP TABLE dbo.People;

SELECTउपरोक्त दो कथनों से आउटपुट हैं:

यहाँ छवि विवरण दर्ज करें

अनिवार्य रूप से, परिणाम लगभग समान है। एक प्रमुख अंतर यह है कि व्यापक प्राकृतिक कुंजी को हर तालिका में दोहराया नहीं जाता है जहां विदेशी कुंजी होती है। मेरे उदाहरण में, मैं VARCHAR(200)उस व्यक्ति का नाम रखने के लिए एक कॉलम का उपयोग कर रहा हूं , जो VARCHAR(200) हर जगह का उपयोग करने की आवश्यकता है । यदि विदेशी कुंजी वाले बहुत सी पंक्तियाँ और बहुत सी सारणियाँ हैं, जो बहुत सारी व्यर्थ स्मृति को जोड़ देंगी। ध्यान दें, मैं डिस्क स्पेस के बारे में बात नहीं कर रहा हूं क्योंकि ज्यादातर लोग कहते हैं कि डिस्क स्पेस इतना सस्ता है जितना अनिवार्य रूप से मुफ्त है। स्मृति, हालांकि, महंगी है और पोषित होने की हकदार है। जब आप लगभग 15 वर्णों की औसत नाम लंबाई पर विचार करते हैं, तो कुंजी के लिए 4-बाइट पूर्णांक का उपयोग करने से बड़ी मात्रा में मेमोरी बच जाएगी।

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


1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx


3
CASCADE से बचने के लिए (जिसमें कुछ परिदृश्यों में समस्याएँ हैं) आप FK कॉलम को अशक्त बना सकते हैं, इसलिए यदि आपको PK को बदलने की आवश्यकता है, तो आप संबंधित पंक्तियों को NULL (क्रम में, यदि बहुत कुछ हो, या तालिका में) अपडेट कर सकते हैं , अगर वहाँ बहुत सारे टेबल हैं, या दोनों), और फिर पीके मान को बदलें, और फिर एफके को फिर से बदलें।
हारून बर्ट्रेंड

8

हालांकि आप एक ऐसी कुंजी का उपयोग कर सकते हैं, जो आपके पीके के रूप में स्वाभाविक और / या परिवर्तनशील है, मेरे अनुभव में जो समस्याओं की ओर ले जाती है, जिसे अक्सर पीके के उपयोग से रोका जा सकता है जो इन शर्तों को पूरा करता है:

 Guaranteed Unique, Always Exists, Immutable, and Concise.

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

मैंने उन परिदृश्यों में से हर एक को देखा है। मैंने ऐसी कंपनियों को भी देखा है जो अपने ग्राहकों को "सिर्फ एक नंबर" नहीं देना चाहती थीं, जिसका मतलब था कि उनका पीके 'पहले + मध्य + अंतिम + डीओबी + ज़िप' या कुछ इसी तरह की बकवास है। जबकि उन्होंने पर्याप्त क्षेत्रों को लगभग विशिष्टता की गारंटी देने के लिए जोड़ा था, उनके प्रश्न भयावह थे, और उन क्षेत्रों में से किसी एक को अपडेट करने का मतलब डेटा स्थिरता मुद्दों का पीछा करना था।

मेरे अनुभव में, डेटाबेस द्वारा उत्पन्न पीके अपने आप में लगभग हमेशा एक बेहतर समाधान है।

मैं अतिरिक्त संकेत के लिए इस लेख की सलाह देता हूं: http://www.agiledata.org/essays/keys.html


6
स्कॉट एंबलर लेख से सलाह का एक अच्छा टुकड़ा आपके उत्तर में संदर्भित है: "कुछ लोग आपको बताएंगे कि आपको हमेशा प्राकृतिक कुंजी का उपयोग करना चाहिए और अन्य आपको बताएंगे कि आपको हमेशा सरोगेट कुंजी का उपयोग करना चाहिए। ये लोग आमतौर पर गलत साबित होते हैं। वे आपके साथ अपने "डेटा धर्म" के पूर्वाग्रहों को साझा करने से थोड़ा अधिक कर रहे हैं। वास्तविकता यह है कि प्राकृतिक और सरोगेट कुंजी प्रत्येक के अपने फायदे और नुकसान हैं, और यह कि कोई भी रणनीति सभी स्थितियों के लिए एकदम सही नहीं है। "
nvogel

7

सिंक्रनाइज़ेशन शामिल होने पर प्राथमिक कुंजी को बदला जा सकता है। यह तब हो सकता है जब आपके पास कोई डिस्कनेक्ट क्लाइंट है और यह कुछ अंतराल पर सर्वर के साथ डेटा को सिंक्रनाइज़ करता है।

कुछ साल पहले मैंने एक ऐसी प्रणाली पर काम किया था, जहां स्थानीय मशीन के सभी ईवेंट डेटा में नकारात्मक पंक्ति Ids, जैसे -1, -2 आदि थे, जब डेटा को सर्वर से सिंक्रनाइज़ किया गया था, तो सर्वर पर पंक्ति क्रमांक लागू किया गया था ग्राहक। मान लीजिए कि सर्वर पर अगली पंक्ति क्रमांक 58 था। फिर -1 58, -2 59 और इसके बाद बन जाएगा। उस पंक्ति ID परिवर्तन को स्थानीय मशीन पर सभी बच्चे FK रिकॉर्ड में कैस्केड किया जाएगा। तंत्र का उपयोग यह निर्धारित करने के लिए भी किया गया था कि कौन से रिकॉर्ड पहले सिंक किए गए थे।

मैं यह नहीं कह रहा हूं कि यह एक अच्छा डिजाइन था, लेकिन यह समय के साथ बदल रही प्राथमिक कुंजी का एक उदाहरण है।


5

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

जैसा कि @MaxVernon द्वारा बताया गया है कि कभी-कभार बदलाव हो सकते हैं - फिर उपयोग करें ON UPDATE CASCADE, हालाँकि आजकल अधिकांश सिस्टम सरोगेट के रूप में एक आईडी का उपयोग करते हैं PRIMARY KEY

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


3

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

एक अधिक दिलचस्प उदाहरण एक तालिका का मामला है जिसमें कई कुंजियाँ होती हैं जहाँ उन कुंजियों में से एक या अधिक मानों को अन्य प्रमुख मूल्यों के संबंध में बदलना पड़ सकता है। दो चाबियों के साथ एक कर्मचारी तालिका का उदाहरण लें: लॉगिननाम और बैज नंबर। यहाँ उस तालिका से एक नमूना पंक्ति है:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZoeS     |47832   |
+---------+--------+

यदि ZoeS अपना बैज खो देता है तो शायद उसे एक नया आवंटित किया जाता है और एक नया बैज नंबर प्राप्त करता है:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZoeS     |50282   |
+---------+--------+

बाद में, वह अपना लॉगिन नाम बदलने का निर्णय ले सकती है:

+---------+--------+
|LoginName|BadgeNum|
+---------+--------+
|ZSmith   |50282   |
+---------+--------+

दोनों प्रमुख मूल्य बदल गए - एक दूसरे के संबंध में। ध्यान दें कि यह आवश्यक रूप से कोई अंतर नहीं रखता है, जिसे "प्राथमिक" माना जाता है।

व्यवहार में "अपरिवर्तनीयता", यानी बिल्कुल कभी भी मूल्य नहीं बदलना, अस्वीकार्य या कम से कम सत्यापित करना असंभव है। इस हद तक कि परिवर्तन से फर्क पड़ता है, सबसे सुरक्षित कोर्स शायद यह मान लेना है कि किसी भी कुंजी (या किसी भी विशेषता) को बदलने की आवश्यकता हो सकती है।


मैंने निम्नलिखित कथन के कारण आपकी टिप्पणी को अस्वीकार कर दिया: "व्यवहार में" अपरिवर्तनीयता ", अर्थात बिल्कुल कभी भी मूल्य नहीं बदलना, अस्वीकार्य या कम से कम असंभव है।" अपरिवर्तनीयता संभव है, और सरोगेट कुंजी का उपयोग करने के लिए सबसे महत्वपूर्ण कारणों में से एक है।
बायरन जोन्स 14

3
आप यह कैसे जान सकते हैं कि कोई अगले सप्ताह या 10 वर्षों के समय में महत्वपूर्ण मूल्य नहीं बदलेगा? आप मान सकते हैं कि वे ऐसा नहीं करेंगे, लेकिन आप वास्तविक रूप से ऐसा नहीं होने से रोक सकते हैं (यदि आप पूरी तरह से चार्ज में हैं तो आप बाधाओं को छोड़ सकते हैं बाकी सभी को मैं हमेशा मानता हूं लेकिन यह एक किनारे के मामले जैसा लगता है)। जो वास्तव में मायने रखता है वह यह है कि परिवर्तन बहुत ही अनियंत्रित हैं, ऐसा नहीं है कि वे कभी भी नहीं होंगे।
नागवैल

3

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

एक आदर्श दुनिया में, ऐसा कभी नहीं होगा। आप प्राथमिक कुंजी के लिए GUIDs का उपयोग शुरू करने के लिए करेंगे। वास्तविक रूप से, हालांकि, आपके पास तब भी वितरित डेटाबेस नहीं हो सकता है जब आप डिज़ाइन करना शुरू करते हैं, और इसे GUID में परिवर्तित करना एक प्रयास हो सकता है जो इसे वितरित करने से पहले प्राथमिकता प्राप्त कर लेता है क्योंकि इसे प्रमुख अद्यतन को लागू करने की तुलना में अधिक प्रभाव माना जाता था। यदि आपके पास एक बड़ा कोड आधार है जो पूर्णांक कुंजियों पर निर्भर करता है और GUID में कनवर्ट करने के लिए बड़े संशोधन की आवश्यकता होगी। यह भी तथ्य है कि GUIDs (GUIDs) जो एक दूसरे के बहुत करीब नहीं हैं, जो तब होता है जब आप उन्हें बेतरतीब ढंग से उत्पन्न करते हैं) प्राथमिक कुंजी के रूप में उन्हें ( बायरन जोन्स द्वारा उल्लिखित )।


0

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


-1

ऐसी स्थिति की कल्पना करें जब किसी ने प्राथमिक बीमा के रूप में राष्ट्रीय बीमा संख्या (एनआईएन) को चुना और किसी तरह एक ऑपरेटर गलत एनआईएन के साथ एक पंक्ति सम्मिलित करता है। मान सम्मिलित करने के बाद, त्रुटि को ठीक करने के दो तरीके हैं:

  1. गलत रिकॉर्ड को हटा दें और एक नया डालें
  2. मान को सही एक पर अपडेट करें और उस स्तंभ पर एक संदर्भात्मक अखंडता बाधा होने पर अपडेट कैस्केड का उपयोग करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.