मैं एक डेटाबेस में IS-A संबंध कैसे बनाऊं?


26

निम्नलिखित को धयान मे रखते हुए:

entity User
{
    autoincrement uid;
    string(20) name;
    int privilegeLevel;
}

entity DirectLoginUser
{
    inherits User;
    string(20) username;
    string(16) passwordHash;
}

entity OpenIdUser
{
    inherits User;
    //Whatever attributes OpenID needs... I don't know; this is hypothetical
}

विभिन्न प्रकार के उपयोगकर्ता (डायरेक्ट लॉगिन उपयोगकर्ता, और ओपनआईडी उपयोगकर्ता) आईएस-ए संबंध प्रदर्शित करते हैं; अर्थात्, दोनों प्रकार के उपयोगकर्ता उपयोगकर्ता हैं। अब, आरडीबीएमएस में यह प्रतिनिधित्व करने के कई तरीके हैं:

रास्ता एक

CREATE TABLE Users
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    type ENUM("DirectLogin", "OpenID") NOT NULL,
    username VARCHAR(20) NULL,
    passwordHash VARCHAR(20) NULL,
    //OpenID Attributes
    PRIMARY_KEY(uid)
)

रास्ता दो

CREATE TABLE Users
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privilegeLevel INTEGER NOT NULL,
    type ENUM("DirectLogin", "OpenID") NOT NULL,
    PRIMARY_KEY(uid)
)

CREATE TABLE DirectLogins
(
    uid INTEGER NOT_NULL,
    username VARCHAR(20) NOT NULL,
    passwordHash VARCHAR(20) NOT NULL,
    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid) REFERENCES Users.uid
)

CREATE TABLE OpenIDLogins
(
    uid INTEGER NOT_NULL,
    // ...
    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid) REFERENCES Users.uid
)

रास्ता तीन

CREATE TABLE DirectLoginUsers
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    username VARCHAR(20) NOT NULL,
    passwordHash VARCHAR(20) NOT NULL,
    PRIMARY_KEY(uid)
)

CREATE TABLE OpenIDUsers
(
    uid INTEGER AUTO_INCREMENT NOT NULL,
    name VARCHAR(20) NOT NULL,
    privlegeLevel INTEGER NOT NULL,
    //OpenID Attributes
    PRIMARY_KEY(uid)
)

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

मेरा वास्तविक विश्व उदाहरण विभिन्न लॉगिन उदाहरण वाले उपयोगकर्ता नहीं हैं; मैं इस मामले में सामान्य स्थिति में कैसे संबंध बनाना चाहता हूं।


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

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

PostgreSQL जैसे ऑब्जेक्ट-रिलेशनल डेटाबेस में, वास्तव में एक चौथा तरीका है: आप किसी तालिका को किसी अन्य तालिका से घोषित कर सकते हैं। postgresql.org/docs/current/static/tutorial-inheritance.html
MarkusSchaber

जवाबों:


16

तरीका दो सही तरीका है।

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

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

उदाहरण के लिए, MySQL DDL कुछ इस तरह दिखाई देगा:

CREATE TABLE Users
(
      uid               INTEGER AUTO_INCREMENT NOT NULL
    , type              ENUM("DirectLogin", "OpenID") NOT NULL
    // ...

    , PRIMARY_KEY(uid)
);

CREATE TABLE DirectLogins
(
      uid               INTEGER NOT_NULL
    , type              ENUM("DirectLogin") NOT NULL
    // ...

    , PRIMARY_KEY(uid)
    , FORIGEN_KEY (uid, type) REFERENCES Users (uid, type)
);

CREATE TABLE OpenIDLogins
(
      uid               INTEGER NOT_NULL
    , type              ENUM("OpenID") NOT NULL
    // ...

    PRIMARY_KEY(uid),
    FORIGEN_KEY (uid, type) REFERENCES Users (uid, type)
);

(अन्य प्लेटफार्मों पर आप CHECKइसके बजाय एक बाधा का उपयोग करेंगे ENUM।) MySQL समग्र विदेशी कुंजियों का समर्थन करता है इसलिए यह आपके लिए काम करना चाहिए।

रास्ता एक वैध है, हालांकि आप उन-जैसे NULLस्तंभों में जगह बर्बाद कर रहे हैं क्योंकि उनका उपयोग उपयोगकर्ता के प्रकार पर निर्भर करता है। लाभ यह है कि यदि आप किस प्रकार के उपयोगकर्ता प्रकारों को संग्रहीत करने के लिए विस्तार करना चुनते हैं और उन प्रकारों को अतिरिक्त स्तंभों की आवश्यकता नहीं है, तो आप बस अपने डोमेन का विस्तार कर सकते ENUMहैं और उसी तालिका का उपयोग कर सकते हैं ।

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


1
मैं इस तथ्य से कैसे निपटूं कि रास्ता 2 का उपयोग करते हुए, यह लागू करने का कोई तरीका नहीं है कि दो अन्य तालिकाओं में बिल्कुल एक समान पंक्ति है?
बिली ओपल

2
@ बिली - अच्छी आपत्ति। यदि आपके उपयोगकर्ता केवल एक या दूसरे हो सकते हैं, तो आप इसे अपनी खरीद परत या ट्रिगर के माध्यम से लागू कर सकते हैं। मुझे आश्चर्य है कि अगर इस बाधा को लागू करने के लिए डीडीएल-स्तरीय तरीका है। (ओह, अनुक्रमित विचारों की अनुमति नहीं UNION है, या मैं के खिलाफ एक अनूठा सूचकांक के साथ एक अनुक्रमित दृश्य सुझाव दिया है | UNION ALLके uidदो तालिकाओं से।)
निक Chammas

बेशक, यह मानता है कि आपके RDBMS ने पहली बार अनुक्रमित विचारों का समर्थन किया है।
बिली ओपल

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

1
@Joel - तो, ​​उदाहरण के लिए, हम typeप्रत्येक उप-प्रकार तालिका में एक स्तंभ जोड़ते हैं जो CHECKबाधा के माध्यम से प्रतिबंधित होता है, जिसमें बिल्कुल एक मान (तालिका का प्रकार) होता है। फिर, हम सब-टेबल विदेशी कुंजियों को सुपर-टेबल में समग्र दोनों पर बनाते हैं uidऔर type। वह सरल है।
निक चामास

5

उनका नामकरण किया जाएगा

  1. सिंगल टेबल इनहेरिटेंस
  2. कक्षा तालिका विरासत
  3. कंक्रीट टेबल विरासत

और सभी के अपने वैध उपयोग हैं और कुछ पुस्तकालयों द्वारा समर्थित हैं। आपको यह पता लगाना होगा कि कौन सा सबसे उपयुक्त है।

कई तालिकाओं के होने से डेटा प्रबंधन आपके एप्लिकेशन कोड पर अधिक ले जाएगा, लेकिन अप्रयुक्त स्थान की मात्रा कम कर देगा।


2
"अतिरिक्त प्राथमिक कुंजी" नामक एक अतिरिक्त तकनीक है। इस तकनीक में, उपवर्ग तालिकाओं में एक स्वतंत्र रूप से निर्दिष्ट प्राथमिक कुंजी आईडी नहीं होती है। इसके बजाय, उपवर्ग तालिकाओं का PK FK है जो सुपरक्लास तालिका का संदर्भ देता है। यह कई लाभ प्रदान करता है, मुख्य रूप से यह आईएस-ए रिश्तों की एक-से-एक प्रकृति को लागू करता है। यह तकनीक क्लास टेबल इनहेरिटेंस पर एक ऐड है।
वाल्टर मिती
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.