डिजाइन पैटर्न - कई अभिभावकों में से एक


13

मैं बहुत बार डेटाबेस में एक स्थिति में आता हूं, जहां एक दी गई तालिका कई अलग-अलग मूल तालिकाओं में से एक को FK कर सकती है। मैंने समस्या के दो समाधान देखे हैं, लेकिन न तो व्यक्तिगत रूप से संतोषजनक है। मैं उत्सुक हूं कि आपने वहां क्या अन्य पैटर्न देखे हैं? इसे करने का कोई बेहतर तरीका है?

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

नोट: नीचे DDL SQL सर्वर के लिए है, लेकिन मेरा प्रश्न किसी भी DBMS पर लागू होना चाहिए।

समाधान 1 - एकाधिक अशक्त FKeys

इस समाधान में एक-से-कई तालिकाओं को जोड़ने वाली तालिका में कई FK कॉलम हैं (संक्षिप्तता के लिए नीचे DDL FK निर्माण नहीं दिखाता है)। अच्छा - इस समाधान में यह अच्छा है कि मेरे पास विदेशी चाबियाँ हैं। एफके की अशक्तता इस सटीक डेटा को जोड़ने के लिए सुविधाजनक और अपेक्षाकृत आसान बनाती है। BAD Querying महान नहीं है क्योंकि इससे संबंधित डेटा प्राप्त करने के लिए N LEFT JOINS या N UNION स्टेटमेंट की आवश्यकता होती है । SQL सर्वर में, विशेष रूप से LEFT JOINS एक अनुक्रमित दृश्य बनाने में शामिल होते हैं।

CREATE TABLE Product (
    ProductID    int identity(1,1) not null,
    CreateUTC    datetime2(7) not null,
     Name        varchar(100) not null
    CONSTRAINT   PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
    CustomerID  int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
     Name       varchar(100) not null
    CONSTRAINT  PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
    NewsID      int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
    Name        varchar(100) not null
    CONSTRAINT  PK_News Primary Key CLUSTERED (NewsID)
)

CREATE TABLE Alert (
    AlertID     int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
    ProductID   int null,
    NewsID      int null,
    CustomerID  int null,
    CONSTRAINT  PK_Alert Primary Key CLUSTERED (AlertID)
)

ALTER TABLE Alert WITH CHECK ADD CONSTRAINT CK_OnlyOneFKAllowed 
CHECK ( 
    (ProductID is not null AND NewsID is     null and CustomerID is     null) OR 
    (ProductID is     null AND NewsID is not null and CustomerID is     null) OR 
    (ProductID is     null AND NewsID is     null and CustomerID is not null) 
)

समाधान 2 - प्रत्येक पैरेंट टेबल में एक FK
इस समाधान में प्रत्येक 'पैरेंट' टेबल में अलर्ट टेबल के लिए FK है। माता-पिता से जुड़े अलर्ट को पुनः प्राप्त करना आसान बनाता है। नीचे की ओर, जो संदर्भ के लिए अलर्ट से कोई वास्तविक श्रृंखला नहीं है। इसके अलावा, डेटा मॉडल अनाथ अलर्ट के लिए अनुमति देता है - जहां कोई अलर्ट उत्पाद, समाचार या ग्राहक से संबद्ध नहीं है। फिर से, एसोसिएशन का पता लगाने के लिए कई बाएँ शामिल हैं।

CREATE TABLE Product (
    ProductID    int identity(1,1) not null,
    CreateUTC    datetime2(7) not null,
     Name        varchar(100) not null
    AlertID     int null,
    CONSTRAINT   PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
    CustomerID  int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
     Name       varchar(100) not null
    AlertID     int null,
    CONSTRAINT  PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
    NewsID      int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
    Name        varchar(100) not null
    AlertID     int null,
    CONSTRAINT  PK_News Primary Key CLUSTERED (NewsID)
)

CREATE TABLE Alert (
    AlertID     int identity(1,1) not null,
    CreateUTC   datetime2(7) not null,
    CONSTRAINT  PK_Alert Primary Key CLUSTERED (AlertID)
)

क्या यह केवल एक रिलेशनशिप डेटाबेस में जीवन है? क्या आपके वैकल्पिक समाधान हैं जो आपको अधिक संतोषजनक लगे हैं?


1
क्या आप निम्नलिखित कॉलम के साथ एक पेरेंट टेबल, एलर्टेबल बना सकते हैं: ID, CreateDate, Name, Type। आप इसे करने के लिए अपने तीन बच्चे टेबल एफके, और अपने अलर्ट केवल एक टेबल, अलर्ट कर सकते हैं।
एके

कुछ मामलों के लिए आप एक अच्छा बिंदु बनाते हैं - प्रभावी रूप से # 3 समाधान। किसी भी समय डेटा तेजी से बढ़ रहा है या स्थानीयकृत है, हालांकि, यह काम नहीं करेगा। उदाहरण के लिए कहें उत्पाद, ग्राहक और समाचार प्रत्येक के पास कई भाषाओं में नाम का समर्थन करने के लिए एक "लैंग" तालिका है। अगर मुझे उपयोगकर्ताओं की मूल भाषा में 'नाम' पहुंचाना है तो मैं इसे स्टोर नहीं कर सकता Alertable। इसका कोई मतलब है?
EBarr

1
@EBarr: "अगर मुझे उपयोगकर्ताओं की मूल भाषा में 'नाम' पहुंचाना है तो मैं इसे अलर्ट में स्टोर नहीं कर सकता। मुझे इससे कोई मतलब नहीं है?" नहीं, यह नहीं है। अपने वर्तमान स्कीमा के साथ, यदि आपको उपयोगकर्ताओं की मूल भाषा में 'नाम' देना है, तो क्या आप इसे उत्पाद, ग्राहक या समाचार तालिका में संग्रहीत कर सकते हैं?
ypercube y

@ypercube मैंने जोड़ा कि उन तालिकाओं में से प्रत्येक में एक संबंधित भाषा तालिका है। मैं एक ऐसे परिदृश्य को तैयार करने का प्रयास कर रहा था जहाँ "नाम" पाठ अनुरोध के अनुसार भिन्न हो सकता है और इस प्रकार अलर्ट में संग्रहीत नहीं किया जा सकता है।
अपराह्न

जब तक यह पहले से ही एक स्वीकृत नाम नहीं है, मैं उस क्वेरी के लिए "ऑक्टोपस जॉइन" शब्द प्रस्तावित करता हूं, जिसे आप सभी अलर्ट और उनके संबद्ध माता-पिता को देखने के लिए करेंगे। :)
नाथन लॉन्ग

जवाबों:


4

मैं दूसरे समाधान को समझता हूं क्योंकि यह लागू नहीं है क्योंकि यह एक (ऑब्जेक्ट) -to- कई (अलर्ट) रिश्ते की पेशकश नहीं करता है।

कड़े 3NF अनुपालन के कारण आप सिर्फ दो समाधानों के लिए अटके हुए हैं।

मैं एक कम युग्मन स्कीमा डिजाइन करूंगा:

CREATE TABLE Product  (ProductID  int identity(1,1) not null, ...)
CREATE TABLE Customer (CustomerID int identity(1,1) not null, ...)
CREATE TABLE News     (NewsID     int identity(1,1) not null, ...)

CREATE TABLE Alert (
  -- See (1)
  -- AlertID     int identity(1,1) not null,

  AlertClass char(1) not null, -- 'P' - Product, 'C' - Customer, 'N' - News
  ForeignKey int not null,
  CreateUTC  datetime2(7) not null,

  -- See (2)
  CONSTRAINT  PK_Alert Primary Key CLUSTERED (AlertClass, ForeignKey)
)

-- (1) you don't need to specify an ID 'just because'. If it's meaningless, just don't.
-- (2) I do believe in composite keys

या, यदि अखंडता संबंध अनिवार्य होगा, तो मैं डिजाइन कर सकता हूं:

CREATE TABLE Product  (ProductID  int identity(1,1) not null, ...)
CREATE TABLE Customer (CustomerID int identity(1,1) not null, ...)
CREATE TABLE News     (NewsID     int identity(1,1) not null, ...)

CREATE TABLE Alert (
  AlertID     int identity(1,1) not null,
  AlertClass char(1) not null, /* 'P' - Product, 'C' - Customer, 'N' - News */
  CreateUTC  datetime2(7) not null,
  CONSTRAINT  PK_Alert Primary Key CLUSTERED (AlertID)
)

CREATE TABLE AlertProduct  (AlertID..., ProductID...,  CONSTRAINT FK_AlertProduct_X_Product(ProductID)    REFERENCES Product)
CREATE TABLE AlertCustomer (AlertID..., CustomerID..., CONSTRAINT FK_AlertCustomer_X_Customer(CustomerID) REFERENCES Customer)
CREATE TABLE AlertNews     (AlertID..., NewsID...,     CONSTRAINT FK_AlertNews_X_News(NewsID)             REFERENCES News)

वैसे भी ...

तीन वैध समाधानों के अलावा कई (वस्तुओं) के लिए विचार किया जाना चाहिए-एक (सतर्क) संबंधों ...

ये प्रस्तुत, क्या नैतिक है?

वे समान रूप से भिन्न होते हैं, और मानदंड पर समान वजन होता है:

  • सम्मिलन और अद्यतन पर प्रदर्शन
  • क्वेरी करने पर जटिलता
  • स्टोरेज की जगह

तो, आप के लिए है कि comfier चुनें।


1
इनपुट के लिए धन्यवाद; मैं आपकी अधिकांश टिप्पणियों से सहमत हूं। मैंने संभवत: कृत्रिम रूप से आवश्यक संबंध (आपकी आंखों में समाधान 2 को छोड़कर) का वर्णन किया, क्योंकि यह एक बना हुआ उदाहरण था। fn1 - समझ में आया, मैं सिर्फ तालिकाओं को सरल बना रहा था ताकि समस्या पर ध्यान दिया जा सके। fn2 - कम्पोज़िट कीज़ और मैं वापस जाता हूँ! पुन: कम युग्मन स्कीमा मैं सरलता को समझता हूं, लेकिन व्यक्तिगत रूप से जहां भी संभव हो DRI के साथ डिजाइन करने का प्रयास करें।
EBarr

इसकी समीक्षा करते हुए, मुझे अपने समाधान की शुद्धता पर संदेह करना शुरू हो गया ... वैसे भी, यह दो बार मतदान हुआ है, जिसका मैं धन्यवाद करता हूं। हालांकि मेरा मानना ​​है कि मेरा डिज़ाइन वैध है, लेकिन दी गई समस्या के लिए उपयुक्त नहीं है, क्योंकि 'एन' यूनियनों / जोड़ों को संबोधित नहीं किया जाता है ...
मार्कस विनीसियस पोम्पे

DRI का परिचय मुझे मिला। आप सभी के लिए, यह डिक्लेरेटिव रेफ़रेंशियल इंटिग्रिटी, रेफ़रेंशियल डेटा इंटिग्रिटी के पीछे की तकनीक है, जिसे आमतौर पर ... (ड्रम रोल) ... DDL FOREIGN KEY स्टेटमेंट्स के रूप में लागू किया जाता है। के बारे में अधिक en.wikipedia.org/wiki/Declarative_Referential_Integrity और msdn.microsoft.com/en-us/library/...
मार्कस विनिसियस Pompeu

1

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.