क्या मुझे सकर्मक विदेशी कुंजी जोड़ना चाहिए?


11

सरल उदाहरण: ग्राहकों की एक तालिका है।

create table Customers (
  id integer,
  constraint CustomersPK primary key (id)
)

डेटाबेस में अन्य सभी डेटा को लिंक करना चाहिए Customer, इसलिए जैसे Ordersदिखता है:

create table Orders (
  id integer,
  customer integer,
  constraint OrdersPK primary key (customer, id),
  constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)

मान लीजिए कि अब एक तालिका है Orders:

create table Items (
  id integer,
  customer integer,
  order integer,
  constraint ItemsPK primary key (customer, id),
  constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)

मैं से एक अलग विदेशी कुंजी जोड़ना चाहिए Itemsकरने के लिए Customers?

...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)

इसके बजाय एक तस्वीर: क्या मुझे धराशायी लाइन / एफके को जोड़ना चाहिए?

सरल उदाहरण स्कीमा


संपादित करें: मैंने प्राथमिक कुंजी परिभाषाओं को तालिकाओं में जोड़ा है। मैं ऊपर दिए गए बिंदु पर पुन: पुनरावृति करना चाहता हूं: डेटाबेस को ग्राहकों द्वारा मूल रूप से एक शुद्धता / सुरक्षा उपाय के रूप में चुप कराया जाता है। इसलिए, सभी प्राथमिक कुंजी में customerID होती है।


2
नहीं, आपको नहीं करना चाहिए। अतिरिक्त FK की कोई आवश्यकता नहीं है। बाधा को अन्य दो एफके द्वारा लागू किया जाता है।
ypercube y

@ypercube क्या कोई निरर्थक एफके होने के लिए कोई प्रदर्शन दंड है? किसी भी फायदे के बारे में आप सोच सकते हैं? ...
vektor

1
। बाधा। बड़ी पीके टेबल के साथ, यह प्रदर्शन जुर्माना काफी गंभीर हो सकता है।
डैनियल हतमाचर

जवाबों:


6

मुझे लगता है कि यह मूल विचार है।

यहाँ छवि विवरण दर्ज करें

पहली बात यह है कि लाइन इटिम टेबल पर पीके में तीन विशेषताएँ हैं {CustomerID, CustomerOrderNo, OdrerItemNo}, जैसा कि आपके उदाहरण में सिर्फ दो के विपरीत है।

ध्यान देने वाली दूसरी बात idएक विशेषता के लिए जेनेरिक नाम के उपयोग से उत्पन्न भ्रम है ।

CustomerOrderNoआदर्श (1,2,3 ..) प्रत्येक ग्राहक और के लिए होना चाहिए OrderItemNoप्रत्येक आदेश के लिए (1,2,3 ...)।

ठीक है, यदि संभव हो तो यह अच्छा है, लेकिन पिछले अधिकतम मूल्य की तलाश में एक क्वेरी की आवश्यकता है, जैसे

select max(CustomerOrderNo)
from Order 
where CustomerID = specific_customer ; 

जो अक्सर उच्च-लेन-देन-मात्रा वाले वातावरण में पसंद नहीं किया जाता है, इसलिए ऑटो-इंक्रीमेंट द्वारा प्रतिस्थापित किया जाना आम है, अनिवार्य रूप से उसी उद्देश्य से सेवा करना। यह सच है कि यह ऑटो-इन्क्रिमेट अब अद्वितीय है, इसलिए इसे एक कुंजी के रूप में इस्तेमाल किया जा सकता है - लेकिन आप इसके लिए आवश्यक समझौता के रूप में देख सकते हैं OrderItemNo

इसलिए, कुछ नाम बदलने CustomerOrderNo -> OrderNoऔर OrderItemNo-> ItemNoआप इस मॉडल पर पहुंच सकते हैं

यहाँ छवि विवरण दर्ज करें

तो अब अगर आप Orderनिम्नलिखित को देखते हैं तो अद्वितीय हैं

{OrderNo}             -- PK
{CustomerID, OrderNo} -- superkey,  AK on the diagram.

ध्यान दें कि एफके के रूप में सेवा {CustomerID, OrderNo}करने के LineItemलिए प्रचार किया जाता है।

यदि आप थोड़ा सा निचोड़ते हैं, तो यह आपके उदाहरण के करीब है, लेकिन PKs {ItemNo} and {OrderNo}केवल - आपके उदाहरण से दो कॉलम पीके के विपरीत।

अब सवाल यह है कि इस तरह से किसी चीज़ का सरलीकरण क्यों नहीं?

यहाँ छवि विवरण दर्ज करें

कौन सा ठीक है, लेकिन प्रस्तुत किया जाने पथ निर्भरता - आप शामिल नहीं हो सकते LineItemसाथ Customer, सीधे का उपयोग करना चाहिए Orderमें शामिल होने में।


मैं संभव होने पर पहला मामला पसंद करता हूं - आप अपना पसंदीदा चुनते हैं। और ज़ाहिर है, वहाँ से सीधे FK के लिए कोई जरूरत नहीं है LineItemकरने के लिए Customerइन तीन मामलों में।


मैंने आस-पास खोज की, लेकिन मैं "पथ निर्भरता" को व्यापक रूप से अपनाए जाने वाले शब्द के रूप में उपयोग नहीं कर सकता, जिसे मैं "2 डिग्री सकर्मक संबंध" के रूप में संदर्भित करूंगा (हालांकि मेरी शब्दावली शायद गलत भी है)
दाई

2

"आइटम" को सीधे "ग्राहक" का संदर्भ नहीं देना चाहिए, क्योंकि यह आइटम के "ऑर्डर" द्वारा निहित है। तो, आपको "आइटम" टेबल पर "ग्राहक" कॉलम की आवश्यकता नहीं होगी।

ग्राहक का आइटम का संबंध मौजूदा विदेशी कुंजी के साथ सुनिश्चित किया जाता है।

यदि order.id एक पहचान स्तंभ है, तो आइटम हटाने पर विचार करें। पूरी तरह से।


1
धन्यवाद, मैंने यह नहीं देखा कि "ग्राहक" को पहले आइटम में "आइटम" से "ऑर्डर" में भी शामिल किया गया था। मैंने अपने उत्तर को उसी के अनुसार विस्तृत किया है।
डैनियल हटमाचर

@DanielHutmacher मैंने अपनी तालिकाओं की प्राथमिक कुंजी रखने के लिए प्रश्न संपादित किया है। यह आपके द्वारा संपादित किए गए अजीब FKs की व्याख्या करता है।
vektor

ठीक है, मैंने अपना जवाब अपडेट कर दिया है। :)
डैनियल हतमाकर

मैं अनुमान लगा रहा हूं कि customerसभी तालिकाओं में (और इस तरह डीबी को सिलो करना) एक असामान्य दृष्टिकोण है। मुझे यह स्वीकार करना चाहिए कि यह सिर्फ कुछ है जो मैंने अपने पिछले काम में देखा है। क्या इससे आपको कोई मतलब है? क्या आपने पहले ऐसा डिज़ाइन देखा है?
vektor

मैं कहूंगा कि यह डेटावेयरहाउस (स्टार स्कीमा) दृष्टिकोण की तरह लगता है, जहां आप जानबूझकर जुड़ने के लिए डेटा को असामान्य रूप से समाप्त करना चाहते हैं। या प्राथमिक कुंजी संमिश्र हो सकती है, अर्थात ग्राहक A का पहला, दूसरा, तीसरा क्रम, ग्राहक B का पहला, दूसरा क्रम, आदि - जब ऑर्डर आईडी कॉलम अकेले अद्वितीय नहीं है।
डैनियल Hutmacher
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.