2012-05-04 11 views
24

इस प्रणाली में, हम उत्पादों को स्टोर करते हैं, उत्पादों की छवियां (उत्पाद के लिए कई छवियां हो सकती हैं), और उत्पाद के लिए एक डिफ़ॉल्ट छवि। डेटाबेस:एसक्यूएल में, क्या यह एक दूसरे के संदर्भ में दो तालिकाओं के लिए ठीक है?

CREATE TABLE `products` (
    `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `NAME` varchar(255) NOT NULL, 
    `DESCRIPTION` text NOT NULL, 
    `ENABLED` tinyint(1) NOT NULL DEFAULT '1', 
    `DATEADDED` datetime NOT NULL, 
    `DEFAULT_PICTURE_ID` int(10) unsigned DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `Index_2` (`DATEADDED`), 
    KEY `FK_products_1` (`DEFAULT_PICTURE_ID`), 
    CONSTRAINT `FK_products_1` FOREIGN KEY (`DEFAULT_PICTURE_ID`) REFERENCES `products_pictures` (`ID`) ON DELETE SET NULL ON UPDATE SET NULL 
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8; 


CREATE TABLE `products_pictures` (
    `ID` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `IMG_PATH` varchar(255) NOT NULL, 
    `PRODUCT_ID` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`ID`), 
    KEY `FK_products_pictures_1` (`PRODUCT_ID`), 
    CONSTRAINT `FK_products_pictures_1` FOREIGN KEY (`PRODUCT_ID`) REFERENCES `products` (`ID`) ON DELETE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC; 

के रूप में आप देख सकते हैं, products_pictures.PRODUCT_ID -> products.ID और products.DEFAULT_PICTURE_ID -> products_pictures.ID, तो एक चक्र संदर्भ। ठीक है न?

+2

यह लेकिन इस पर भरोसा नहीं करना चाहिए। आप कुछ रिकॉर्ड जोड़ने का प्रयास क्यों नहीं करते हैं और फिर उन्हें हटाने का प्रयास करते हैं। – Deepesh

उत्तर

34

नहीं, यह ठीक नहीं है। तालिकाओं के बीच परिपत्र संदर्भ गन्दा हैं। यह देखें (दशक पुराना) आलेख: SQL By Design: The Circular Reference

कुछ डीबीएमएस इन्हें और विशेष देखभाल के साथ संभाल सकते हैं, लेकिन MySQL में समस्याएं होंगी।


पहली पसंद दो FKS में से एक नल बनाने के लिए अपने डिजाइन के रूप में, है। यह आपको चिकन-एंड-अंडे की समस्या को हल करने की अनुमति देता है (मुझे किस तालिका में पहले डालना चाहिए?)।

आपके कोड के साथ एक समस्या है। यह किसी उत्पाद को एक डिफ़ॉल्ट तस्वीर रखने की अनुमति देगा जहां वह तस्वीर किसी अन्य उत्पाद का संदर्भ देगी!

इस तरह के एक त्रुटि अनुमति रद्द करने के अपने FK बाधा होना चाहिए:

CONSTRAINT FK_products_1 
    FOREIGN KEY (id, default_picture_id) 
    REFERENCES products_pictures (product_id, id) 
    ON DELETE RESTRICT       --- the SET NULL options would 
    ON UPDATE RESTRICT       --- lead to other issues 

यह FK ऊपर के लिए (product_id, id) पर तालिका products_pictures में एक UNIQUE बाधा/सूचकांक की आवश्यकता से परिभाषित करने की है और ठीक से काम करेंगे।


एक और दृष्टिकोण Default_Picture_ID स्तंभ product तालिका फार्म को हटा दें और picture तालिका में एक IsDefault BIT स्तंभ जोड़ने के लिए है। इस समाधान के साथ समस्या यह है कि प्रति उत्पाद केवल एक तस्वीर को उस बिट पर रखने की अनुमति दें और अन्य सभी इसे बंद कर दें। एसक्यूएल सर्वर-(और मैं Postgres में लगता है) इस एक आंशिक सूचकांक के साथ किया जा सकता है:

CREATE UNIQUE INDEX is_DefaultPicture 
    ON products_pictures (Product_ID) 
    WHERE IsDefault = 1 ; 

लेकिन MySQL में ऐसी कोई सुविधा है।


एक तीसरा दृष्टिकोण है, जो आप भी दोनों FK स्तंभों के रूप में परिभाषित NOT NULL deferrable की कमी उपयोग करने के लिए है की अनुमति देता है। यह PostgreSQL में काम करता है और मुझे ओरेकल में लगता है। इस प्रश्न और उत्तर @Erwin: Complex foreign key constraint in SQLAlchemy (सभी कुंजी कॉलम न्यूल भाग) द्वारा उत्तर दें।

MySQL में बाधाएं डिफ्रैबल नहीं हो सकती हैं।


चौथा दृष्टिकोण (जो मैं साफ लगता है) Default_Picture_ID कॉलम हटाकर एक और तालिका जोड़ना है। FK की कमी और सभी FK कॉलम में कोई वृत्तीय पथ इस समाधान के साथ NOT NULL हो जाएगा:

product_default_picture 
---------------------- 
product_id   NOT NULL 
default_picture_id NOT NULL 
PRIMARY KEY (product_id) 
FOREIGN KEY (product_id, default_picture_id) 
    REFERENCES products_pictures (product_id, id) 

यह भी समाधान 1.


में के रूप में एक UNIQUE बाधा/ (product_id, id) पर तालिका products_pictures में सूचकांक की आवश्यकता होगी

संक्षेप में, MySQL के साथ दो विकल्प हैं: साथ

  • विकल्प 1 (एक नल FK स्तंभ) सुधार ऊपर अखंडता लागू करने के लिए सही ढंग से

  • विकल्प 4 (कोई नल FK कॉलम)

+1

@ किल्रावर पर एक नज़र डालें: thnx –

+0

यह एक शानदार अवलोकन (+1) है, लेकिन मुझे नहीं लगता कि क्या लाभ विकल्प 4 विकल्प 1 से अधिक है। विकल्प 1 के साथ, बग्गी एप्लिकेशन कोड उत्पाद बनाकर अमान्य डेटा बना सकता है और इसे कभी भी 'default_picture_id' नहीं दे सकता है। विकल्प 4 के साथ, बग्गी एप्लिकेशन कोड समान रूप से उत्पाद बनाकर अमान्य डेटा बना सकता है और इसके लिए कभी भी 'product_default_picture' पंक्ति नहीं बना सकता है। हालांकि, अपने डिफ़ॉल्ट चित्रों के साथ उत्पादों को एक साथ चुनने के लिए अब और अधिक जुड़ने की आवश्यकता है, और स्कीमा कम आत्म-दस्तावेज है। अतिरिक्त जटिलता को समाप्त करने के प्रारंभिक दृष्टिकोण पर हमें क्या लाभ मिला है? –

+2

@MarkAmery एक और जुड़ाव एक समस्या का नहीं है, है ना? चौथे समाधान के लिए एक लाभ तब प्रकट होता है जब किसी को डिफ़ॉल्ट चित्रों के लिए अधिक विशेषताओं को स्टोर करने की आवश्यकता होती है। यह शून्य समाधान के साथ पहले समाधान में भी काम कर सकता है, लेकिन MySQL के पास उस मामले में 'जांच' बाधाओं को लागू करने का कोई तरीका नहीं है (यह सुनिश्चित करने के लिए कि ऐसे सभी अतिरिक्त गुण या तो न्यूल हैं या न्यूल नहीं हैं)। –

-1

कि एक चक्रीय रेफरी नहीं है, कि PK-FK

+0

मेरा मतलब था, "ए" का अर्थ है "बी" और "बी" का अर्थ "ए" है, क्या इससे कुछ चोट नहीं पहुंची? –

+1

कुछ भी तोड़ नहीं रहा है, मेरा मानना ​​है कि आपको ईएफ कोड के नियमों पर एक नज़र डालना चाहिए और यदि संभव हो तो आरडीबीएमएस – Satya

4

यह सिर्फ सुझाव है, लेकिन यदि संभव हो तो बनाने में शामिल होने पर नज़र रखने

product_productcat_join 
------------------------ 
ID(PK) 
ProductID(FK)- product table primary key 
PictureID(FK) - category table primary key 
2

केवल मुद्दा आप के लिए इस तालिका के बीच तालिका मददगार हो सकता है जब आप आवेषण करते हैं तो मुठभेड़ में जा रहा है। आप पहले किससे सम्मिलित करते हैं?

इस के साथ

, आप की तरह कुछ करना होगा:

  • अशक्त डिफ़ॉल्ट चित्र के साथ सम्मिलित करें उत्पाद
  • चित्र (रों) नव निर्मित उत्पाद आईडी
  • अद्यतन स्थापित करने के लिए उत्पाद के साथ सम्मिलित करें आपके द्वारा अभी डाला गया एक डिफ़ॉल्ट चित्र।

फिर से, हटाना मजेदार नहीं होगा।

0

जॉन क्या आपके बुरा नहीं है कुछ भी करने लेकिन का उपयोग कर PK-FK वास्तव में अनावश्यक दोहरा डेटा को हटाने के द्वारा अपने डेटा को सामान्य के साथ मदद करता है । जो एक ही डेटा

  • कम लॉकिंग विवाद के लिए डुप्लिकेट भंडारण स्थान के उन्मूलन के कारण

    • बेहतर डेटा अखंडता से कुछ शानदार फायदे हैं और बेहतर बहु-उपयोगकर्ता संगामिति
    • छोटे फ़ाइलों
  • संबंधित मुद्दे

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