आत्म संदर्भित तालिकाओं, अच्छा या बुरा? [बन्द है]


37

किसी एप्लिकेशन के भीतर भौगोलिक स्थानों का प्रतिनिधित्व करते हुए, अंतर्निहित डेटा मॉडल का डिज़ाइन दो स्पष्ट विकल्प (या शायद अधिक?) का सुझाव देता है।

सेल्फ रेफरेंसिंग पैरेंट_ड कॉलम uk के साथ एक टेबल - लंदन (लंदन पैरेंट आईडी = यूके आईडी)

या एक विदेशी कुंजी का उपयोग कर कई संबंधों के साथ दो टेबल।

मेरी प्राथमिकता एक स्वयं-संदर्भित तालिका के लिए है क्योंकि यह आसानी से आवश्यकतानुसार कई उप क्षेत्रों में विस्तार करने की अनुमति देता है।

आम तौर पर लोग आत्म-संदर्भित तालिकाओं से दूर भागते हैं, या वे ए-ओके हैं?

जवाबों:


40

आत्म-संदर्भित तालिकाओं के साथ कुछ भी गलत नहीं है।

यह गहरी (अनंत?) नेस्टेड पदानुक्रम के लिए सामान्य डेटाबेस डिज़ाइन पैटर्न है।


@NimChimpsky - पुनरावृत्ति की अवधारणा की तरह, यह विचार कुछ के लिए मुश्किल है।
Oded

2
(कम से कम) ऑरेकल में एक विशेष एसक्यूएल संदूक भी है, "स्टार्ट विथ - कनेक्ट बाय" क्लॉज, सेल्फ-रेफरेंसिंग टेबल से निपटने के लिए।
13:28 पर user281377

1
@ user281377 - और SQL सर्वर ने hierarchyidप्रकार पेश किया ।
Oded

usign hibernate तो इसकी अपनी विशेष चटनी होगी
NimChimpsky

4
@NimChimpsky - उस "पैरेंट_ड" कॉलम के विकल्प के रूप में "नेस्टेड सेट मॉडल" को देखने पर विचार करें - यह समान कार्यक्षमता प्रदान करता है, लेकिन पदानुक्रम निकालने के लिए बेहतर प्रदर्शन और आसान प्रश्न। en.wikipedia.org/wiki/Nested_set_model जो सेल्को की पुस्तक श्रृंखला "एसक्यूएल फॉर स्मार्टीज़" में नेस्टेड सेट के बारे में कुछ बेहतरीन नमूना एसक्यूएल है।
कीथ पामर जूनियर

7

Necromancing।
सही उत्तर है: यह किस डेटाबेस इंजन और किस प्रबंधन उपकरण पर निर्भर करता है।

आइए एक उदाहरण बनाते हैं:
हमारे पास एक रिपोर्ट तालिका है,
और एक रिपोर्ट में एक माता-पिता (रजोनिवृत्ति, जैसे श्रेणी) हो सकते हैं,
और यह कि माता-पिता के पास माता-पिता (जैसे लाभ केंद्र) हो सकते हैं,
और इसलिए विज्ञापन infinitum।

किसी भी स्व-संदर्भित इकाई / पदानुक्रम के साथ मानक पुनरावर्ती संबंध का सबसे सरल उदाहरण।

परिणामी SQL- सर्वर तालिका है:

IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'dbo.FK_T_FMS_Reports_T_FMS_Reports') AND parent_object_id = OBJECT_ID(N'dbo.T_FMS_Reports'))
ALTER TABLE dbo.T_FMS_Reports DROP CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.T_FMS_Reports') AND type in (N'U'))
DROP TABLE dbo.T_FMS_Reports 
GO



CREATE TABLE dbo.T_FMS_Reports 
( 
     RE_UID uniqueidentifier NOT NULL 
    ,RE_RE_UID uniqueidentifier NULL 
    ,RE_Text nvarchar(255) NULL 
    ,RE_Link nvarchar(400) NULL 
    ,RE_Sort int NOT NULL 
    ,RE_Status int NOT NULL 
    ,PRIMARY KEY CLUSTERED ( RE_UID ) 
); 

GO

ALTER TABLE dbo.T_FMS_Reports  WITH CHECK ADD  CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports FOREIGN KEY(RE_RE_UID) 
REFERENCES dbo.T_FMS_Reports (RE_UID) 
-- ON DELETE CASCADE -- here, MS-SQL has a problem 
GO

ALTER TABLE dbo.T_FMS_Reports CHECK CONSTRAINT FK_T_FMS_Reports_T_FMS_Reports 
GO

लेकिन आपको एक समस्या मिलती है:
जब आपको अपने सभी सबमेन्यूपॉइंट्स के साथ एक मेन्यूपॉइंट को हटाने की आवश्यकता होती है, तो आप डिलीट-कैस्केड सेट नहीं कर सकते , क्योंकि Microsoft SQL-Server पुनरावर्ती कैस्केड डिलीट का समर्थन नहीं करता है (दूसरी तरफ, पोस्टकार्ड SQL करता है [लेकिन केवल तभी) ग्राफ चक्रीय नहीं है], जबकि MySQL इस तरह की तालिका संरचना को बिल्कुल पसंद नहीं करता है, क्योंकि यह पुनरावर्ती सीटीई का समर्थन नहीं करता है)।

तो आप इसके साथ विलोपन-अखंडता / कार्यक्षमता को उड़ा देते हैं, जिससे आपके अपने कोड में या किसी संग्रहीत कार्यविधि (यदि आपका RDBMS संग्रहीत कार्यविधियों का समर्थन करता है) में ऐसी कार्यक्षमता को लागू करना अनिवार्य हो जाता है।

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

उदाहरण के लिए, जब आप SSMS का उपयोग करके एक INSERT स्क्रिप्ट बनाते हैं, तो SSMS को विदेशी कुंजी नहीं मिलेगी, और इस तरह यह वास्तव में ऐसे इंसर्टमेंट बनाते हैं जो निर्भरता के साथ प्रविष्टियाँ सम्मिलित करेंगे, इससे पहले कि यह निर्भरता के जनक को सम्मिलित करता है, जो एक त्रुटि के साथ विफल हो जाएगा , क्योंकि विदेशी कुंजी की जगह है।

हालांकि, उचित टूलींग के साथ, उचित डेटाबेस प्रबंधन प्रणालियों (जैसे कि PostgreSQL) पर, यह एक समस्या नहीं होनी चाहिए। सिर्फ इसलिए कि आप अपने RDBMS के लिए बहुत कुछ चुकाते हैं (मैं आपको Microsoft; Oracle =? और न ही OpenSource (जैसे MySQL) आपको ऐसे अद्भुत minutiae के लिए प्रतिरक्षा बनाता है।

शैतान विवरण में है, जैसा कि पुरानी कहावत है।

अब, ऐसा नहीं है कि आप ऐसी समस्याओं के आसपास काम नहीं कर सकते हैं, लेकिन मैं वास्तव में इसकी सिफारिश नहीं करूंगा, अगर आपका सिस्टम जटिल होने वाला है (जैसे 200+ टेबल)।
इसके अलावा, एक सामान्य व्यावसायिक सेटिंग में (जैसा कि दिलबर्ट द्वारा चित्रित किया गया है), आपको बस उस समय नहीं दिया जाएगा।

अधिक बेहतर दृष्टिकोण, हालांकि अधिक कठिन, एक क्लोजर टेबल होगा।
इसमें अतिरिक्त बोनस होगा जो MySQL पर भी काम करता है।
एक बार जब आप एक बार क्लोजर-कार्यक्षमता को लागू कर लेते हैं, तो आपके पास इसे अतिरिक्त स्थानों पर लगभग सभी समय पर काम करना होगा।


3
मेरे ध्यान में क्लोजर टेबल लाने पर (कम से कम शब्दावली, पहले से ही अवधारणा पता था)। यहाँ पर एक अच्छा लेख है अन्य के लिए जो रुचि हो सकती है। coderwall.com/p/lixing/closure-tables-for-browsing-trees-in-sql
आउट सोर्स सोर्स

1

यह एक अच्छा विचार है यदि संबंध वास्तव में पदानुक्रमित है, और नेटवर्क संबंध नहीं है (उदाहरण के लिए बिल ऑफ़ मटेरियल एक नेटवर्क संबंध है, न कि एक पदानुक्रमित)।

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

http://karwin.blogspot.ca/2010/03/rendering-trees-with-closure-tables.html

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