2011-10-21 5 views
79

मुझे अपने डेटाबेस में 3 प्रासंगिक टेबल मिल गए हैं।एकाधिक तालिकाओं के लिए विदेशी कुंजी

CREATE TABLE dbo.Group 
(
    ID int NOT NULL, 
    Name varchar(50) NOT NULL 
) 

CREATE TABLE dbo.User 
(
    ID int NOT NULL, 
    Name varchar(50) NOT NULL 
) 

CREATE TABLE dbo.Ticket 
(
    ID int NOT NULL, 
    Owner int NOT NULL, 
    Subject varchar(50) NULL 
) 

उपयोगकर्ता कई समूहों से संबंधित हैं। यह कई रिश्तों के माध्यम से किया जाता है, लेकिन इस मामले में अप्रासंगिक है। एक टिकट या तो किसी समूह या उपयोगकर्ता के स्वामित्व में हो सकता है, dbo.Ticket.Owner फ़ील्ड के माध्यम से।

सबसे अच्छा तरीका टिकट और वैकल्पिक रूप से उपयोगकर्ता या समूह के बीच इस संबंध का वर्णन करेगा?

मुझे लगता है कि मुझे टिकट तालिका में एक झंडा जोड़ना चाहिए जो कहता है कि इसका किस प्रकार का मालिक है।

+0

हर टिकट एक समूह के स्वामित्व में है। यह सिर्फ एक उपयोगकर्ता है जो एक समूह है। @ नाथन-स्कर्ल मॉडल से कौन सा विकल्प 4। यदि आप गुड्स को चाबियों के रूप में उपयोग करते हैं तो पूरी चीज भी अच्छी तरह से काम करती है – GraemeMiller

उत्तर

99

आपके पास कुछ विकल्प हैं, जो सभी "शुद्धता" और उपयोग में आसानी से भिन्न होते हैं। हमेशा की तरह, सही डिजाइन आपकी आवश्यकताओं पर निर्भर करता है।

  • आप बस टिकट, OwnedByUserId और OwnedByGroupId में दो कॉलम बना सकते हैं, और प्रत्येक मेज पर नल FKS है।

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

  • आप प्रत्येक उपयोगकर्ता के लिए एक डिफ़ॉल्ट समूह बना सकते हैं और टिकटों का स्वामित्व केवल एक वास्तविक समूह या उपयोगकर्ता के डिफ़ॉल्ट समूह के स्वामित्व में हो सकता है।

  • या (मेरी पसंद) एक इकाई है जो उपयोगकर्ता और समूहों दोनों के लिए आधार के रूप में कार्य करती है, और उस इकाई द्वारा टिकट मालिक है।

उसके बारे में यहां किसी न किसी उदाहरण आपके पोस्ट स्कीमा का उपयोग कर:

create table dbo.PartyType 
( 
    PartyTypeId tinyint primary key, 
    PartyTypeName varchar(10) 
) 

insert into dbo.PartyType 
    values(1, 'User'), (2, 'Group'); 


create table dbo.Party 
(
    PartyId int identity(1,1) primary key, 
    PartyTypeid tinyint references dbo.PartyType(PartyTypeId), 
    unique (PartyId, PartyTypeId) 
) 

CREATE TABLE dbo.[Group] 
(
    ID int NOT NULL, 
    Name varchar(50) NOT NULL, 
    PartyTypeId as cast(2 as tinyint) persisted, 
    foreign key (ID, PartyTypeId) references Party(PartyId, PartyTypeID) 
) 

CREATE TABLE dbo.[User] 
(
    ID int NOT NULL, 
    Name varchar(50) NOT NULL, 
    PartyTypeId as cast(1 as tinyint) persisted, 
    foreign key (ID, PartyTypeId) references Party(PartyID, PartyTypeID) 
) 

CREATE TABLE dbo.Ticket 
(
    ID int NOT NULL, 
    [Owner] int NOT NULL references dbo.Party(PartyId), 
    [Subject] varchar(50) NULL 
) 
+0

आपके समाधान ने मुझे बहुत मदद की, धन्यवाद – mxasim

+4

विकल्प विकल्प 4 के लिए +1 विकल्प। – Catchops

+2

उपयोगकर्ता/समूह टिकट के लिए कोई प्रश्न कैसा दिखता है? धन्यवाद। – paulkon

-2
CREATE TABLE dbo.OwnerType 
(
    ID int NOT NULL, 
    Name varchar(50) NULL 
) 

insert into OwnerType (Name) values ('User'); 
insert into OwnerType (Name) values ('Group'); 

मुझे लगता है कि ध्वज का उपयोग करने के बजाय आप जो चाहते हैं उसका प्रतिनिधित्व करने का सबसे सामान्य तरीका होगा।

24

@Nathan Skerl की सूची में पहले विकल्प क्या एक परियोजना मैं एक बार, साथ जहां एक समान संबंध के बीच स्थापित किया गया था काम में लागू किया गया था है तीन टेबल (उनमें से एक ने दो अन्य लोगों का संदर्भ दिया, एक समय में।)

तो, संदर्भ तालिका में दो विदेशी कुंजी कॉलम थे, और यह भी गारंटी देने की बाधा थी कि बिल्कुल एक तालिका (दोनों न तो, न तो नहीं) संदर्भित की गई थी एक पंक्ति से

यहाँ जब आपके तालिका में लागू किए यह कैसा नज़र आ सकता है:

CREATE TABLE dbo.[Group] 
(
    ID int NOT NULL CONSTRAINT PK_Group PRIMARY KEY, 
    Name varchar(50) NOT NULL 
); 

CREATE TABLE dbo.[User] 
(
    ID int NOT NULL CONSTRAINT PK_User PRIMARY KEY, 
    Name varchar(50) NOT NULL 
); 

CREATE TABLE dbo.Ticket 
(
    ID int NOT NULL CONSTRAINT PK_Ticket PRIMARY KEY, 
    OwnerGroup int NULL 
     CONSTRAINT FK_Ticket_Group FOREIGN KEY REFERENCES dbo.[Group] (ID), 
    OwnerUser int NULL 
     CONSTRAINT FK_Ticket_User FOREIGN KEY REFERENCES dbo.[User] (ID), 
    Subject varchar(50) NULL, 
    CONSTRAINT CK_Ticket_GroupUser CHECK (
     CASE WHEN OwnerGroup IS NULL THEN 0 ELSE 1 END + 
     CASE WHEN OwnerUser IS NULL THEN 0 ELSE 1 END = 1 
    ) 
); 

आप देख सकते हैं, Ticket तालिका में दो कॉलम, OwnerGroup और OwnerUser, जो दोनों के नल विदेशी चाबियाँ हैं है। (अन्य दो तालिकाओं में संबंधित कॉलम तदनुसार प्राथमिक कुंजी बनाये जाते हैं।) CK_Ticket_GroupUser चेक बाधा सुनिश्चित करता है कि केवल दो विदेशी कुंजी स्तंभों में से एक संदर्भ में एक संदर्भ है (दूसरा नल है, यही कारण है कि दोनों को निरर्थक होना चाहिए)।

(Ticket.ID पर प्राथमिक कुंजी इस विशेष कार्यान्वयन के लिए आवश्यक नहीं है, लेकिन यह निश्चित रूप से इस तरह एक तालिका में एक है करने के लिए नुकसान नहीं होगा।)

मेरे मन के लिए
+0

यह हमारे सॉफ़्टवेयर में भी है और यदि आप एक सामान्य डेटा एक्सेस फ्रेमवर्क बनाने की कोशिश कर रहे हैं तो मैं इससे बचूंगा। यह डिज़ाइन ऐप परत में जटिलता बढ़ाएगा। –

+0

मैं वास्तव में एसक्यूएल के लिए नया हूं इसलिए यदि यह गलत है तो मुझे सही करें, लेकिन यह डिज़ाइन उपयोग करने का एक दृष्टिकोण प्रतीत होता है जब आप बेहद आत्मविश्वास रखते हैं कि आपको केवल दो मालिक प्रकार के टिकट की आवश्यकता होगी। सड़क के नीचे यदि कोई तीसरा टिकट मालिक प्रकार पेश किया गया था, तो आपको तालिका में तीसरा नामुमकिन विदेशी कुंजी कॉलम जोड़ना होगा। – Shadoninja

+0

@Shadoninja: आप गलत नहीं हैं। वास्तव में, मुझे लगता है कि इसे डालने का एक बिल्कुल सही तरीका है। मैं आम तौर पर इस तरह के समाधान के साथ ठीक हूं जहां यह उचित है, लेकिन विकल्पों पर विचार करते समय यह निश्चित रूप से मेरे दिमाग पर पहले नहीं होगा - ठीक उसी कारण के कारण जो आपने रेखांकित किया है। –

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

  • कोई संबंधित समस्या नहीं^_^