MySQL में विदेशी कुंजी बाधा को अस्थायी रूप से कैसे अक्षम करें?


651

क्या MySQL में बाधाओं को अस्थायी रूप से अक्षम करना संभव है?

मेरे पास दो Django मॉडल हैं, प्रत्येक एक विदेशी के साथ एक दूसरे को। किसी मॉडल के उदाहरणों को हटाने से फ़ॉरेनके की बाधा के कारण त्रुटि होती है:

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()  #a foreign key constraint fails here

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

क्या बाधाओं को अस्थायी रूप से अक्षम करना और वैसे भी हटाना संभव है?


3
या तो मुझे वह नहीं मिलता जो आप करना चाहते हैं, या आप जो करने की कोशिश कर रहे हैं वह बहुत, बहुत, बहुत बदसूरत है । अगर आप ऐसा कर सकते हैं, तो भी आपको नहीं करना चाहिए।
डेरियस

3
एक FK को छोड़ना और पुनः प्राप्त करना आपके db को बदल रहा है। आप बहुत अड़चनों को टालने की कोशिश कर रहे हैं जो सिस्टम को कुछ अर्थों को देखने की अनुमति देता है, इसका कोई संबंध नहीं है कि एफके एक अस्थायी चीज हो सकती है, और अगर यह पता था, तो यह घबराहट होगी।
ग्रांट थॉमस

1
यह अजीब है कि आप क्या करने की कोशिश कर रहे हैं। लेकिन आप किस डेटाबेस का उपयोग कर रहे हैं?
andrefsp

4
क्या होगा, यदि आप अपने अवरोध को अक्षम करने के बजाय, आपने इसे स्थायी रूप से संशोधित किया है ON DELETE SET NULL? यह एक समान बात को पूरा करेगा और आपको मुख्य जांच को चालू और बंद नहीं करना पड़ेगा।
dnagirl

1
@dnagirl: यह वास्तव में बेहतर होगा। मैं उसे कैसे कर सकता हूँ?
जूल

जवाबों:


1466

कोशिश करो DISABLE KEYSया

SET FOREIGN_KEY_CHECKS=0;

यह सुनिश्चित कर लें

SET FOREIGN_KEY_CHECKS=1;

उपरांत।


14
क्या यह कुछ ऐसा है जो mysql के लिए संपूर्ण या केवल उस सत्र के लिए निर्धारित है?
टिपू

28
मेरा मानना ​​है कि यह प्रति सत्र है।
एंड्रयू कैंपबेल

13
serverfault.com/questions/291100/… , यह भी ध्यान दें कि आप इनोडब के लिए नहीं disable keys कर सकते
Pacerier

1
क्या मैं केवल एक तालिका के लिए FOREIGN_KEY_CHECKS अक्षम कर सकता हूं?
jDub9

@Pacerier पढ़ने से, ऐसा लगता है कि आप कर सकते हैं, लेकिन केवल एक सत्र के लिए।
ब्रेट

150

विश्व स्तर पर विदेशी प्रमुख बाधा को बंद करने के लिए, निम्नलिखित कार्य करें:

SET GLOBAL FOREIGN_KEY_CHECKS=0;

और याद रखें कि जब आप कर रहे हों तो इसे वापस सेट करें

SET GLOBAL FOREIGN_KEY_CHECKS=1;

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


1
यह वही है जो मुझे जानने की जरूरत है, इसलिए इसका महान अभ्यास नहीं है, लेकिन इस लड़के का जवाब उच्च स्कोरिंग होना चाहिए ...
22

1
यह मेरे लिए 'सर्वश्रेष्ठ जवाब' की कोशिश करने के बाद मेरे लिए काम नहीं किया। शायद अंतर का स्पष्टीकरण जोड़ा जा सकता है।
हेक्सनेट

7
@hexnet अंतर यह है कि बस है SET FOREIGN_KEY_CHECKSबस के लिए मूल्य में परिवर्तन वर्तमान कनेक्शन है, जबकि SET GLOBAL ..के लिए मूल्य में परिवर्तन सभी कनेक्शनों भविष्य कनेक्शन भी शामिल है। यदि आप सिर्फ SET FOREIGN..एक विंडो में करते हैं, तो एक अलग विंडो (एक अलग कनेक्शन पर) में स्टेटमेंट को लागू करने का प्रयास करें, वहां मान नहीं बदला गया है। साथ GLOBAL, दोनों कनेक्शन के लिए एक ही चर का एक ही मूल्य है।
मतलिन्द

केवल एक चीज जो बड़े डंप (6+ जीबी) को वापस खेलने में मेरी मदद कर सकती थी <3
मैक्स

यह मेरे लिए काम नहीं करता है। जब मैं कोशिश करता हूं, तो मैं देखता हूं:ERROR 1228 (HY000): Variable 'foreign_key_checks' is a SESSION variable and can't be used with SET GLOBAL
माइक बी

53

जब मैं किसी तालिका को छोटा करना चाहता हूं, तो मैं सामान्य रूप से केवल विदेशी कुंजी बाधाओं को अक्षम करता हूं, और जब से मैं इस उत्तर पर वापस आता हूं, तो यह मेरे लिए है:

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE TABLE table;
SET FOREIGN_KEY_CHECKS=1;

25

अपने अवरोध को अक्षम करने के बजाय, इसे स्थायी रूप से DELETE SET NULL पर संशोधित करें। यह एक समान बात को पूरा करेगा और आपको मुख्य जांच चालू और बंद नहीं करनी होगी। इस तरह:

ALTER TABLE tablename1 DROP FOREIGN KEY fk_name1; //get rid of current constraints
ALTER TABLE tablename2 DROP FOREIGN KEY fk_name2;

ALTER TABLE tablename1 
  ADD FOREIGN KEY (table2_id) 
        REFERENCES table2(id)
        ON DELETE SET NULL  //add back constraint

ALTER TABLE tablename2 
  ADD FOREIGN KEY (table1_id) 
        REFERENCES table1(id)
        ON DELETE SET NULL //add back other constraint

इसे पढ़ें ( http://dev.mysql.com/doc/refman/5.5/en/alter-table.html ) और यह ( http://dev.mysql.com/doc/refman/5.5/en /create-table-foreign-keys.html )।


7
सर्वर FOREIGN_KEY_CHECKSको 0 के लिए वैश्विक सेट करने और गंदा काम पूरा होने के बाद इसे वापस रखने में बेहतर है, तो फेरबदल करने वाली तालिका में लंबा समय लग सकता है। इसके अलावा यह आपके टेबल लिखने के लिए लॉक हो सकता है।
आकि

दूरस्थ स्तंभ प्रकार में फेरबदल करते समय संदर्भ नहीं तोड़ेंगे? (ऐसा लगता है कि मेरा मुवक्किल मूल तालिका के नाम में एक संशोधित अस्थायी तालिका का नाम बदल देता है।)
सीस टिमरमैन

15

विश्व स्तर पर विदेशी प्रमुख बाधा को बंद करने के लिए:

SET GLOBAL FOREIGN_KEY_CHECKS = 0;

और सक्रिय विदेशी कुंजी बाधा के लिए

SET GLOBAL FOREIGN_KEY_CHECKS = 1;

10

Phpmyadmin के साथ एक बहुत ही सरल उपाय:

  • अपनी तालिका में, SQLटैब पर जाएं
  • SQL कमांड जिसे आप चलाना चाहते हैं, उसे संपादित करने के बाद, बगल में एक चेक बॉक्स है GO, जिसका नाम ' विदेशी कुंजी चेक सक्षम करें' है
  • इस चेक बॉक्स को अनचेक करें और अपना SQL चलाएं । इसे निष्पादित करने के बाद स्वचालित रूप से फिर से जांच की जाएगी।

3
धन्यवाद! वास्तव SET FOREIGN_KEY_CHECKS=0; ..... SET FOREIGN_KEY_CHECKS=1;में PHPMyAdmin में समाधान मेरे काम नहीं आया क्योंकि मैं 'विदेशी कुंजी जांच सक्षम' चेकबॉक्स को अनचेक करना भूल गया था। PHPMyAdmin में आप इन SET कमांड को छोड़ सकते हैं और चेकबॉक्स को अनचेक कर सकते हैं।
Jan

5

मेरे लिए बस SET FOREIGN_KEY_CHECKS=0;पर्याप्त नहीं था। मैं अभी भी एक था com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException

मुझे जोड़ना था ALTER TABLE myTable DISABLE KEYS;

इसलिए:

SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE myTable DISABLE KEYS;
DELETE FROM myTable;
ALTER TABLE myTable ENABLE KEYS;
SET FOREIGN_KEY_CHECKS=1;

FYI करें, mySQL 5.7 थ्रो की चेतावनी, इनोबीडी इंजन में डिसेबल कुंजी कमांड चलाने पर यह विकल्प नहीं है।
jDub9

यह काम नहीं किया, परिवर्तन तालिका के बिना यह भी मेरे लिए काम नहीं किया
डेविड काबी

3

यदि कुंजी फ़ील्ड अशक्त है, तो आप इसे हटाने का प्रयास करने से पहले मान को शून्य करने के लिए भी सेट कर सकते हैं:

cursor.execute("UPDATE myapp_item SET myapp_style_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed() 

cursor.execute("UPDATE myapp_style SET myapp_item_id = NULL WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_item WHERE n = %s", n)
transaction.commit_unless_managed()

cursor.execute("DELETE FROM myapp_style WHERE n = %s", n)
transaction.commit_unless_managed()

2

PhpMyAdmin में आप कई पंक्तियों का चयन कर सकते हैं, फिर हटाएँ कार्रवाई पर क्लिक करें। आप एक स्क्रीन दर्ज करेंगे, जो डिलीट क्वेरीज़ को सूचीबद्ध करती है, आप फॉरेन की जाँच को अनचेक कर सकते हैं, और उन्हें निष्पादित करने के लिए Yes पर क्लिक कर सकते हैं।

यह आपको पंक्तियों को हटाने में सक्षम करेगा, भले ही कोई DELETE प्रतिबंध प्रतिबंध हो।


-2

विदेशी कुंजी बाधा को 0 पर सेट करना एक अच्छा विचार नहीं है, क्योंकि यदि आप करते हैं, तो आपका डेटाबेस यह सुनिश्चित नहीं करेगा कि यह संदर्भात्मक अखंडता का उल्लंघन नहीं कर रहा है। इससे गलत, भ्रामक या अधूरा डेटा हो सकता है।

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

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

कल्पना करें कि यह बड़ी मात्रा में डेटा के लिए होता है। इसलिए आपको विदेशी कुंजी जांच की आवश्यकता है।

यह पता लगाना सबसे अच्छा है कि त्रुटि का कारण क्या है। सबसे अधिक संभावना है, आप चाइल्ड रो से हटाए बिना मूल पंक्ति से हटाने का प्रयास कर रहे हैं। पैरेंट पंक्ति से हटाने से पहले चाइल्ड रो को हटाने का प्रयास करें।


सच है, वहाँ हमेशा एक व्यापार बंद है।
पचेरियर

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

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

3
यह सवाल का जवाब नहीं है।
कोरे तुगे

ध्यान दें, उनका सवाल यह है कि यह अस्थायी रूप से कैसे किया जाए। कुछ रखरखाव और डेटा आयात करते समय इसकी आवश्यकता होती है। निश्चित रूप से चेतावनी यह है कि आपकी आयात स्क्रिप्ट डेटा अखंडता के लिए जिम्मेदार बन जाती हैं। फिर, बाद में जब सूचकांक और बाधाओं को वापस चालू किया जाता है, तो डीबी आपको बताएगा कि क्या कुछ टूट गया है।
mcstar
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.