एक समग्र विदेशी कुंजी एक विदेशी कुंजी है जिसमें कई कॉलम होते हैं।
यह आलेख SQL सर्वर में Transact-SQL का उपयोग करके एक समग्र विदेशी कुंजी बनाने का एक उदाहरण प्रदान करता है।
आप एक समग्र विदेशी कुंजी बना सकते हैं जैसे आप एक एकल विदेशी कुंजी बनाते हैं, सिवाय इसके कि केवल एक कॉलम निर्दिष्ट करने के बजाय, आप अल्पविराम द्वारा अलग किए गए दो या अधिक कॉलम का नाम प्रदान करते हैं।
इस तरह:
CONSTRAINT FK_FKName विदेशी कुंजी (FKColumn1, FKColumn2)संदर्भ प्राथमिककीटेबल (PKColumn1, PKColumn2)
उदाहरण 1 - एक समग्र विदेशी कुंजी बनाएं
यहां एक मिश्रित विदेशी कुंजी (और एक समग्र प्राथमिक कुंजी) का उपयोग करने वाले डेटाबेस का एक उदाहरण दिया गया है।
इस उदाहरण के लिए, मैं BandTest . नामक एक डेटाबेस बनाऊंगा :
डेटाबेस बैंडटेस्ट बनाएं;
अब जब डेटाबेस बन गया है, तो चलिए आगे बढ़ते हैं और टेबल बनाते हैं।
बैंडटेस्ट का उपयोग करें; टेबल संगीतकार बनाएं (MusicianId int NOT NULL, FirstName varchar (60), LastName varchar (60), CONSTRAINT PK_Musician PRIMARY KEY (MusicianID)); टेबल बैंड बनाएं (BandId int NULL, BandName varchar (255) , CONSTRAINT PK_Band PRIMARY KEY (BandId)); CREATE TABLE BandMember (MusicianId int NOT NULL, BandId int NOT NULL, CONSTRAINT PK_BandMember PRIMARY KEY (MusicianID, BandId), CONSTRAINT FK_BANDINCId) कुंजी (MusicianId) संदर्भ संगीतकार (MusicianId)); तालिका सदस्यता अवधि बनाएं (सदस्यता अवधि आईडी पूर्ण नहीं है, MusicianId int NULL, BandId int NULL नहीं, प्रारंभ दिनांक पूर्ण नहीं, समाप्ति दिनांक अवधि पूर्ण, CONSTRAINT PRIDK_Membership (सदस्यता) KEY (MusicianID, BandId) संदर्भ BandMember(MusicianID, BandId));
इस उदाहरण में, BandMember
तालिका में एक बहु-स्तंभ प्राथमिक कुंजी है। MembershipPeriod
तालिका में एक विदेशी कुंजी है जो उस बहु-स्तंभ प्राथमिक कुंजी का संदर्भ देती है। इसलिए, प्राथमिक और विदेशी दोनों कुंजी परिभाषाओं में अल्पविराम द्वारा अलग किए गए कॉलम शामिल हैं।
उपरोक्त डेटाबेस डिज़ाइन के पीछे तर्क यह है कि, एक संगीतकार संभावित रूप से कई बैंड का सदस्य हो सकता है। साथ ही, प्रत्येक बैंड में कई संगीतकार हो सकते हैं। इसलिए हमारे बीच कई-से-अनेक संबंध हैं। यही कारण है कि BandMember
तालिका बनाई जाती है - इसका उपयोग Musician
. के बीच एक क्रॉस-रेफरेंस तालिका के रूप में किया जाता है टेबल और Band
टेबल। इस मामले में, मैंने समग्र प्राथमिक कुंजी का उपयोग करना चुना है।
लेकिन एक संगीतकार एक से अधिक अवसरों पर बैंड का सदस्य भी हो सकता है (उदाहरण के लिए एक संगीतकार बैंड छोड़ सकता है, केवल बाद में लौटने के लिए)। इसलिए, MembershipPeriod
तालिका का उपयोग उन सभी अवधियों को रिकॉर्ड करने के लिए किया जा सकता है जो प्रत्येक संगीतकार प्रत्येक बैंड का सदस्य रहा है। इसे BandMember
. पर समग्र प्राथमिक कुंजी को संदर्भित करने की आवश्यकता है तालिका, और इसलिए मुझे एक बहु-स्तंभ विदेशी कुंजी बनाने की आवश्यकता है।
उदाहरण 2 - डेटा डालें
उपरोक्त कोड को चलाने के बाद, अब मैं डेटाबेस को डेटा के साथ लोड कर सकता हूं:
संगीतकार मूल्यों में सम्मिलित करें (1, 'इयान', 'पैस' ),( 2, 'रोजर', 'ग्लोवर' ),( 3, 'रिची', 'ब्लैकमोर' ),( 4, 'रॉड', ' इवांस'), (5, 'ओजी', 'ऑस्बॉर्न'); बैंडवैल्यूज़ में डालें (1, 'डीप पर्पल'), (2, 'रेनबो'), (3, 'व्हाइटस्नेक'), (4, 'आयरन मेडेन') ' ); BandMemberVALUES में डालें ( 1, 1 ),( 1, 3 ),( 2, 1 ),( 2, 2 ),( 3, 1 ),( 3, 2 ),( 4, 1 ); INSERT INTO सदस्यता अवधि मान (1, 1, 1, '1968-03-01', '1976-03-15'), (2, 1, 1, '1984-04-01', NULL), (3, 1, 3, '1979-08-01', '1982-01-01' ),( 4, 2, 1, '1969-01-01', '1973-06-29'),( 5, 2, 1, '1984 -04-01', NULL ),( 6, 2, 2, '1979-01-01', '1984-01-01'),( 7, 3, 1, '1968-03-01', '1975 -06-21' ),( 8, 3, 1, '1984-04-01', '1993-11-17' ),( 9, 3, 2, '1975-02-01', '1984-04 -01' ),( 10, 3, 2, '1993-11-17', '1997-05-31'),(11, 3, 2, '2015-01-01', NULL),( 12, 4, 1, '1968-03-01', '1969-12-01');
उदाहरण 3 - मूल प्रश्न
यहां एक क्वेरी का उदाहरण दिया गया है जिसे डेटाबेस के विरुद्ध चलाया जा सकता है:
चुनें CONCAT(m.FirstName, '' ', m.LastName) as 'Musician', b.BandName as 'Band', mp.StartDate as 'Start', mp.EndDate as 'End' from Musician mJOIN BandMember bm m.MusicianId =bm.MusicianIdJOIN Band b पर b.BandId =bm.BandId और m.MusicianId =bm.MusicianIdJOIN MembershipPeriod mpON mp.BandId =b.BandId और mp.MusicianId =m.M.परिणाम:
+---------------------+----------------+---------------+ ------------+| संगीतकार | बैंड | प्रारंभ | अंत ||---------------------+---------------+-----------+- -----------|| इयान पेस | डीप पर्पल | 1968-03-01 | 1976-03-15 || इयान पेस | डीप पर्पल | 1984-04-01 | शून्य || इयान पेस | व्हाइटस्नेक | 1979-08-01 | 1982-01-01 || रोजर ग्लोवर | डीप पर्पल | 1969-01-01 | 1973-06-29 || रोजर ग्लोवर | डीप पर्पल | 1984-04-01 | शून्य || रोजर ग्लोवर | इंद्रधनुष | 1979-01-01 | 1984-01-01 || रिची ब्लैकमोर | डीप पर्पल | 1968-03-01 | 1975-06-21 || रिची ब्लैकमोर | डीप पर्पल | 1984-04-01 | 1993-11-17 || रिची ब्लैकमोर | इंद्रधनुष | 1975-02-01 | 1984-04-01 || रिची ब्लैकमोर | इंद्रधनुष | 1993-11-17 | 1997-05-31 || रिची ब्लैकमोर | इंद्रधनुष | 2015-01-01 | शून्य || रॉड इवांस | डीप पर्पल | 1968-03-01 | 1969-12-01 |+---------------------+---------------+---------- ------------------+इसलिए अब हम देख सकते हैं कि प्रत्येक संगीतकार प्रत्येक बैंड का सदस्य कौन-सा दिनांक था, भले ही वे अनेक अवसरों पर सदस्य रहे हों।
उदाहरण 4 - थोड़ा संशोधित क्वेरी
परिणामों को थोड़ा अधिक पठनीय प्रारूप में प्रदान करने के लिए हम उपरोक्त क्वेरी को संशोधित कर सकते हैं:
CONCAT(m.FirstName, '', m.LastName) AS 'Musician', b.BandName as 'Band', STRING_AGG(CONCAT(FORMAT(mp.StartDate, 'yyyy'), '-', ISNULL चुनें (FORMAT(mp.EndDate, 'yyyy'), 'pretent')), ',') AS 'टाइम विद बैंड' फ्रॉम म्यूजिशियन mJOIN BandMember bm ON m.MusicianId =bm.MusicianIdJOIN Band b ON b.BandId =bm .BandId और m.MusicianId =bm.MusicianIdJOIN MembershipPeriod mpON mp.BandId =b.BandId और mp.MusicianId =m.MusicianIdGROUP by m.FirstName, m.LastName, b.BandName;परिणाम:
+---------------------+----------------+--------------- -----------------------+| संगीतकार | बैंड | बैंड के साथ समय ||---------------------+----------------+---------- -------------------------|| इयान पेस | डीप पर्पल | 1968-1976, 1984-वर्तमान || इयान पेस | व्हाइटस्नेक | 1979-1982 || रिची ब्लैकमोर | डीप पर्पल | 1968-1975, 1984-1993 || रिची ब्लैकमोर | इंद्रधनुष | 1975-1984, 1993-1997, 2015-वर्तमान || रॉड इवांस | डीप पर्पल | 1968-1969 || रोजर ग्लोवर | डीप पर्पल | 1969-1973, 1984-वर्तमान || रोजर ग्लोवर | इंद्रधनुष | 1979-1984 | ------------------------+यह उदाहरण
STRING_AGG()
. का लाभ उठाता है प्रत्येक संगीतकार के लिए विभिन्न समय अवधियों को संयोजित करने का कार्य करता है। यह आवश्यक पंक्तियों की संख्या को कम करता है, और हमें एक ही क्षेत्र में समय अवधि को एक साथ समूहित करने की अनुमति देता है।मैं
ISNULL()
. का भी लाभ उठाता हूं फ़ंक्शन, जो मुझे किसी भी NULL मान को और अधिक सार्थक में बदलने की अनुमति देता है।ध्यान दें कि
ISNULL()
यह आवश्यक है कि दूसरा तर्क एक प्रकार का हो जिसे परोक्ष रूप से पहले तर्क के प्रकार में परिवर्तित किया जा सकता है। इस मामले में, पहला तर्क मूल रूप से तारीख . था प्रकार, जिसका अर्थ है कि मैं एक स्ट्रिंग का उपयोग नहीं कर पाऊंगा। हालांकि, इस मामले में मैंनेFORMAT()
. का उपयोग करने का निर्णय लिया दिनांक . को प्रारूपित करने के लिए कार्य करता है मूल्य। यह फ़ंक्शन परोक्ष रूप से तारीख . को रूपांतरित करता है एक स्ट्रिंग के लिए मान, और इसलिए मैं दूसरे तर्क के लिए एक स्ट्रिंग का उपयोग करने में सक्षम था।