विदेशी प्रमुख बाधाएं: जब अद्यतन और चालू का उपयोग करें


196

मैं MySQL कार्यक्षेत्र का उपयोग करके अपने डेटाबेस स्कीमा को डिजाइन कर रहा हूं, जो बहुत अच्छा है क्योंकि आप आरेख कर सकते हैं और यह उन्हें धर्मान्तरित करता है: P

वैसे भी, मैंने विदेशी कुंजी समर्थन के कारण InnoDB का उपयोग करने का निर्णय लिया है। एक बात जो मैंने देखी है, वह यह है कि यह आपको विदेशी कुंजियों के लिए ऑन अपडेट और डिलीट विकल्पों पर सेट करने की अनुमति देता है। क्या कोई समझा सकता है कि "प्रतिबंधित", "कैस्केड" और सेट नल को एक सरल उदाहरण में कैसे इस्तेमाल किया जा सकता है?

उदाहरण के लिए, मान लीजिए कि मेरे पास एक userतालिका है जिसमें एक शामिल है userID। और कहते हैं कि मेरे पास एक संदेश तालिका है messageजो कई-से-बहुत है जिसमें 2 विदेशी कुंजियाँ हैं (जो तालिका userIDमें समान प्राथमिक कुंजी का संदर्भ देती हैं user)। क्या इस मामले में ऑन अपडेट और ऑन डिलीट ऑप्शंस कोई उपयोगी है? यदि हां, तो मुझे कौन सा चुनना है? यदि यह एक अच्छा उदाहरण नहीं है, तो क्या आप यह बताने के लिए एक अच्छे उदाहरण के साथ आ सकते हैं कि ये कैसे उपयोगी हो सकते हैं?

धन्यवाद

जवाबों:


485

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

MySQL के साथ आपके पास उन्नत अवरोध नहीं होते हैं जैसे कि आप postgreSQL में होते हैं लेकिन कम से कम विदेशी कुंजी बाधाएँ काफी उन्नत होती हैं।

हम एक उदाहरण लेंगे, एक कंपनी तालिका जिसमें उपयोगकर्ता तालिका होती है जिसमें थ्रेस कंपनी के लोग होते हैं

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

आइए नजर डालते हैं UPDATE क्लॉज पर:

  • अद्यतन विवरण पर : डिफ़ॉल्ट : यदि आप टेबल में एक company_id को अपडेट करने का प्रयास करते हैं तो कंपनी इस इंजन को इस कंपनी पर कम से कम लिंक होने पर ऑपरेशन को अस्वीकार कर देगी।
  • अद्यतन नहीं अधिनियम : RESTRICT के समान।
  • पर अद्यतन CASCADE : आमतौर पर सबसे अच्छा एक : यदि आप तालिका कंपनी की एक पंक्ति में एक company_id अद्यतन इंजन इस कंपनी को संदर्भित सभी उपयोगकर्ता पंक्तियों (लेकिन कोई भी ट्रिगर उपयोगकर्ता की मेज पर सक्रिय, चेतावनी) पर तदनुसार अपडेट कर देगा। इंजन आपके लिए परिवर्तनों को ट्रैक करेगा, यह अच्छा है।
  • अद्यतन सेट पर : यदि आप तालिका की एक पंक्ति में एक company_id को अपडेट करते हैं तो कंपनी NULL (USER company_id फ़ील्ड में उपलब्ध होनी चाहिए) से संबंधित USERs company_id सेट करेगी। मैं किसी भी दिलचस्प चीज़ को अपडेट पर नहीं देख सकता, लेकिन मैं गलत हो सकता हूं।

और अब DELETE की तरफ:

  • DELETE RESTRICT : डिफ़ॉल्ट : यदि आप किसी company_id आईडी को टेबल में हटाने का प्रयास करते हैं तो कंपनी ऑपरेशन को अस्वीकार कर देगी यदि एक USER कम से कम इस कंपनी से लिंक करता है, तो आपका जीवन बच सकता है।
  • DELETE NO ACTION : RESTRICT के समान
  • DELETE CASCADE पर : खतरनाक : यदि आप तालिका में किसी कंपनी की पंक्ति हटाते हैं तो कंपनी इंजन संबंधित USER को हटा देगी। यह खतरनाक है, लेकिन इसका उपयोग माध्यमिक तालिकाओं पर स्वचालित सफाई करने के लिए किया जा सकता है (इसलिए यह कुछ ऐसा हो सकता है जो आप चाहते हैं, लेकिन निश्चित रूप से कंपनी के लिए नहीं <-> USER उदाहरण)
  • DELETE SET NULL : मुट्ठी भर पर : यदि आप किसी कंपनी की पंक्ति हटाते हैं तो संबंधित USER अपने आप NULL से संबंध बना लेगा। यदि नल किसी भी कंपनी के साथ उपयोगकर्ताओं के लिए आपका मूल्य है, तो यह एक अच्छा व्यवहार हो सकता है, उदाहरण के लिए शायद आपको अपने एप्लिकेशन में उपयोगकर्ताओं को कुछ सामग्री के लेखकों के रूप में रखने की आवश्यकता है, लेकिन कंपनी को हटाना आपके लिए कोई समस्या नहीं है।

आमतौर पर मेरा डिफ़ॉल्ट है: अपडेट के आधार पर अपडेट करेंON DELETE CASCADEट्रैक टेबल के लिए कुछ (लॉग - सभी लॉग नहीं -, उस तरह की चीजें) और ON DELETE SET NULLजब मास्टर टेबल विदेशी कुंजी वाली तालिका के लिए एक 'सरल विशेषता' है, तो USER तालिका के लिए एक JOB तालिका की तरह।

संपादित करें

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

MySQL ट्रिगर केवल SQL स्टेटमेंट द्वारा तालिकाओं में किए गए परिवर्तनों के लिए सक्रिय होता है। वे विचारों में परिवर्तन के लिए सक्रिय नहीं होते हैं, और न ही एपीआई द्वारा किए गए तालिकाओं में परिवर्तन के द्वारा जो MySQL सर्वर पर SQL स्टेटमेंट को प्रसारित नहीं करते हैं

==> अंतिम संपादन के नीचे देखें, इस डोमेन पर चीजें आगे बढ़ रही हैं

ट्रिगर विदेशी कुंजी क्रियाओं द्वारा सक्रिय नहीं होते हैं।

और मुझे नहीं लगता कि यह एक दिन तय हो जाएगा। विदेशी प्रमुख बाधाओं को InnoDb भंडारण द्वारा प्रबंधित किया जाता है और ट्रिगर MySQL SQL इंजन द्वारा प्रबंधित किया जाता है। दोनों अलग हो गए। इंसोडब प्रबंधन के साथ इनोडब एकमात्र भंडारण है, शायद वे एक दिन सीधे भंडारण इंजन में ट्रिगर जोड़ देंगे, शायद नहीं।

लेकिन मेरी अपनी राय है कि आपको खराब ट्रिगर कार्यान्वयन और बहुत उपयोगी विदेशी कुंजी के बीच किस तत्व का समर्थन करना चाहिए। और एक बार जब आप डेटाबेस की संगति के लिए अभ्यस्त हो जाएंगे तो आपको PostgreSQL से प्यार होगा।

12/2017-यह अपडेट MySQL के बारे में संपादित करें:

जैसा कि @IstiaqueAhmed ने टिप्पणियों में कहा है, इस विषय पर स्थिति बदल गई है। तो लिंक का पालन करें और वास्तविक स्थिति की जांच करें (जो भविष्य में फिर से बदल सकती है)।


8
ON DELETE CASCADE : dangerous- एक चुटकी नमक के साथ लें।
onedaywhen

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

1
व्यापार तर्क के संदर्भ में, वहाँ एक मामले कि के लिए दिलचस्प हो सकता है SET NULLएक में ON UPDATEएक कंपनी को अद्यतन करने के कंपनी> उपयोगकर्ता संबंध की एक टुकड़ी का प्रतिनिधित्व करता है:। उदाहरण: यदि कोई कंपनी अपना व्यवसाय प्रकार बदलती है, तो पिछले उपयोगकर्ता अब उस व्यवसाय से संबंधित नहीं हो सकते हैं, इसलिए NULLइस सूचकांक के लिए बेहतर हो सकता है।
CPHPython 12

1
@regilero, ऐसा लगता है कि आपके पहले लिंक ( dev.mysql.com/doc/refman/5.6/en/triggers.html ) में सामग्री mysql साइट में बदल गई है। इसके This includes changes to base tables that underlie updatable viewsबजाय यह कहता है कि आपने क्या किया हैThey do not activate for changes in views
इस्तियाक अहमद

6
"मैं नहीं चाहूंगा कि ग्राहक अपने पहले के आदेशों के लिए वित्तीय डेटा मिटा दें।" इस तरह की स्थिति में, आपको अभी भी वैसे भी ग्राहक के डेटा की आवश्यकता होती है। आपका डिज़ाइन संभवतः ग्राहक को निष्क्रिय के रूप में चिह्नित करना चाहिए, डेटाबेस से उनकी पंक्ति को हटाना नहीं। व्यवहार में, यह मेरा पेशेवर अनुभव रहा है कि आप वास्तव में बहुत कम ही कुछ हटाना चाहते हैं , डिफ़ॉल्ट रूप से निष्क्रिय चिह्नित करना पसंद करते हैं। ऐसे मामलों में जहां स्थायी रूप से हटाया जा रहा में है ठीक है, CASCADE DELETEआम तौर पर भी, ठीक भी पसंद किया जाता है। मैं इसे विशेष रूप से खतरनाक नहीं मानता।
ग्रैंडऑपनर

3

@MarkR के उत्तर के लिए जोड़ - एक बात ध्यान देने वाली यह होगी कि ORM के साथ कई PHP फ्रेमवर्क उन्नत DB सेटअप (विदेशी कुंजी, कैस्केडिंग डिलीट, अद्वितीय बाधाओं) को पहचान या उपयोग नहीं करेंगे, और इसका परिणाम अप्रत्याशित व्यवहार हो सकता है।

उदाहरण के लिए यदि आप ORM का उपयोग करके कोई रिकॉर्ड हटाते हैं, और आपका DELETE CASCADEरिकॉर्ड संबंधित तालिकाओं में रिकॉर्ड हटा देगा, तो ORM के इन संबंधित रिकॉर्ड (अक्सर स्वचालित) को हटाने के प्रयास में त्रुटि होगी।


11
यह उस विशेष ORM का उपयोग नहीं करने का कारण होगा। कोई भी उपकरण जो डेटाबेस समर्थन में गरीब है भरोसेमंद नहीं है। विदेशी कुंजी और कैस्केडिंग डिलीट या अपडेट डीबी मूल बातें हैं उन्नत अवधारणाएं नहीं हैं और किसी भी वास्तविक डेटाबेस को विदेशी कुंजी बाधाओं के बिना कभी भी डिज़ाइन नहीं किया जाना चाहिए!
HLGEM

समस्या यह है कि वे त्रुटियों को फेंक देते हैं। क्या यह संभव है DELETES लेकिन इंजन में त्रुटियाँ उत्पन्न नहीं हुई हैं लेकिन फिर भी शब्दार्थ बनाए हुए हैं? मैं चाहूंगा कि मेरा कार्यक्रम अभी भी जारी रहे जबकि उसी समय अन्य डेटा को डिलीट होने से बचाएं।
TheRealChx101

2

आपको आवेदन के संदर्भ में इस पर विचार करना होगा। सामान्य तौर पर, आपको एक एप्लिकेशन डिज़ाइन करना चाहिए, न कि डेटाबेस (डेटाबेस केवल एप्लिकेशन का हिस्सा हो सकता है)।

इस बात पर विचार करें कि आपके आवेदन को विभिन्न मामलों में कैसे जवाब देना चाहिए।

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

व्यक्तिगत रूप से, मैं InnoDB का उपयोग करूंगा क्योंकि यह आपके डेटा को ट्रैश नहीं करता है (cf MyISAM, जो करता है), बजाय इसके कि इसमें FK की कमी है।

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