मूल पंक्ति को हटाना या अपडेट नहीं कर सकता: एक विदेशी कुंजी बाधा विफल रहती है


170

जब कर रहे हैं:

DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1 

यह त्रुटियाँ हैं:

#1451 - Cannot delete or update a parent row: a foreign key constraint fails 
(paymesomething.advertisers, CONSTRAINT advertisers_ibfk_1 FOREIGN KEY 
(advertiser_id) REFERENCES jobs (advertiser_id))

यहाँ मेरे टेबल हैं:

CREATE TABLE IF NOT EXISTS `advertisers` (
  `advertiser_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password` char(32) NOT NULL,
  `email` varchar(128) NOT NULL,
  `address` varchar(255) NOT NULL,
  `phone` varchar(255) NOT NULL,
  `fax` varchar(255) NOT NULL,
  `session_token` char(30) NOT NULL,
  PRIMARY KEY (`advertiser_id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `advertisers` (`advertiser_id`, `name`, `password`, `email`, `address`, `phone`, `fax`, `session_token`) VALUES
(1, 'TEST COMPANY', '', '', '', '', '', '');

CREATE TABLE IF NOT EXISTS `jobs` (
  `job_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `advertiser_id` int(11) unsigned NOT NULL,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `longdesc` text NOT NULL,
  `address` varchar(255) NOT NULL,
  `time_added` int(11) NOT NULL,
  `active` tinyint(1) NOT NULL,
  `moderated` tinyint(1) NOT NULL,
  PRIMARY KEY (`job_id`),
  KEY `advertiser_id` (`advertiser_id`,`active`,`moderated`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;


INSERT INTO `jobs` (`job_id`, `advertiser_id`, `name`, `shortdesc`, `longdesc`, `address`, `active`, `moderated`) VALUES
(1, 1, 'TEST', 'TESTTEST', 'TESTTESTES', '', 0, 0);

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

जवाबों:


108

जैसा कि, आपको विज्ञापन तालिका में पंक्ति को हटाना होगा, इससे पहले कि आप नौकरियों की तालिका में पंक्ति को हटा दें जो इसे संदर्भित करता है। यह:

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `jobs` (`advertiser_id`);

... वास्तव में इसके विपरीत होना चाहिए। जैसा कि यह है, इसका मतलब है कि आपको विज्ञापनदाताओं के समक्ष नौकरियों की तालिका में रिकॉर्ड रखना होगा। तो आपको उपयोग करने की आवश्यकता है:

ALTER TABLE `jobs`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `advertisers` (`advertiser_id`);

एक बार जब आप विदेशी कुंजी संबंध ठीक कर लेते हैं, तो आपका डिलीट स्टेटमेंट काम करेगा।


3
पहली पंक्ति में: क्या आपको नहीं लगता कि यह "यह संदर्भ" के बजाय "यह संदर्भ" होना चाहिए? या मुझे गलतफहमी हुई है कि संदर्भ शब्दावली को कैसे काम करना चाहिए?
अब्राहम फिलिप

6
@AbrahamPhilip मैं एक ही बात सोच रहा था। विज्ञापनदाताओं ने नौकरियों का संदर्भ दिया।
कीसर

270

विदेशी कुंजी जांच को अक्षम करने का सरल तरीका होगा; तब परिवर्तन करें जब विदेशी कुंजी जांच फिर से सक्षम हो।

SET FOREIGN_KEY_CHECKS=0; -- to disable them
SET FOREIGN_KEY_CHECKS=1; -- to re-enable them

171
यह समस्या का हल नहीं है, बल्कि एक गंदा काम है जिसके आसपास वांछित नहीं हो सकता है।
मैडफ्रेंड

20
मेरे मामले में: मैं बस एक बड़ी एसक्यूएल फ़ाइल चलाता था और अंतिम बयानों में से एक विफल हो गया था, इसलिए मैं बस सभी तालिकाओं को हटाना चाहता हूं, वाक्यविन्यास त्रुटि को ठीक करना, और पुनर्मिलन करना, यह वही बनाता है जो मैं देख रहा था।
हकीर

1
यदि आप ऐसा करने जा रहे थे, तो सभी बाधाओं को दूर क्यों नहीं किया?
सेबलफोस्ट

1
कुछ ऐसा करते समय यह उपयोगी है:REPLACE INTO tab_with_constraint ...
Maciek 28ozi Decski

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

38

आपके वर्तमान (संभवतः त्रुटिपूर्ण) डिज़ाइन के तहत, आपको विज्ञापन तालिका में पंक्ति को हटाना होगा, इससे पहले कि आप उन नौकरियों की तालिका में पंक्ति को हटा सकें जो आपके संदर्भ में हैं।

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

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1`
FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

यह कहते हुए कि, जैसा कि अन्य लोग पहले ही बता चुके हैं, आपकी विदेशी कुंजी ऐसा महसूस करती है कि इसे दूसरे तरीके से जाना चाहिए क्योंकि विज्ञापन तालिका में वास्तव में प्राथमिक कुंजी होती है और नौकरियों की तालिका में विदेशी कुंजी होती है। मैं इसे इस तरह से फिर से लिखूंगा:

ALTER TABLE `jobs`
ADD FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`);

और कैस्केडिंग हटाना आवश्यक नहीं होगा।


18

यदि आप एक तालिका छोड़ना चाहते हैं, तो आपको एक ही चरण में निम्नलिखित क्वेरी को निष्पादित करना चाहिए

SET FOREIGN_KEY_CHECKS = 0; ड्रॉप टेबल_नाम;


13

मैंने @Alino Manzi द्वारा बताए गए समाधान की कोशिश की, लेकिन यह wpdb का उपयोग करते हुए वर्डप्रेस से संबंधित तालिकाओं पर मेरे लिए काम नहीं किया।

फिर मैंने नीचे दिए गए कोड को संशोधित किया और इसने काम किया

SET FOREIGN_KEY_CHECKS=OFF; //disabling foreign key

//run the queries which are giving foreign key errors

SET FOREIGN_KEY_CHECKS=ON; // enabling foreign key

6

मुझे लगता है कि आपकी विदेशी कुंजी पीछे की ओर है। प्रयत्न:

ALTER TABLE 'jobs'
ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`)

5

यदि एक ही विज्ञापनकर्ता के पास एक से अधिक कार्य हैं, तो आपकी विदेशी कुंजी होनी चाहिए:

ALTER TABLE `jobs`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `advertisers` (`advertiser_id`);

अन्यथा (यदि आपके मामले में इसका दूसरा तरीका गोल है), यदि आप चाहते हैं कि यदि विज्ञापन में पंक्तियों को स्वचालित रूप से हटा दिया जाए तो नौकरी से पंक्ति हटा दी जाए, तो अपनी विदेशी कुंजी के अंत में 'ON DELETE CASCADE' विकल्प जोड़ें:

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

विदेशी कुंजी बाधाओं की जाँच करें


3

आपको इसे क्रम से हटाने की आवश्यकता है तालिकाओं में निर्भरता है


2

जब आप डेटाबेस बनाते हैं या टेबल बनाते हैं

आपको उस पंक्ति को शीर्ष स्क्रिप्ट पर डेटाबेस या तालिका बनाना चाहिए

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;

अब आप तालिका से रिकॉर्ड हटाना चाहते हैं? तो आप के रूप में लिखते हैं

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1

सौभाग्य!


2

इस विकल्प का मैं कैसे उपयोग कर रहा हूं: विदेशी कुंजी को NULL होने दें और फिर DELETE SET NULL चुनें

निजी तौर पर मैं अनावश्यक जटिलताओं से बचने के लिए " ON UPDATE CASCADE " के साथ-साथ " ON DELETE SET NULL " दोनों का उपयोग करना पसंद करता हूं , लेकिन अपने सेट अप पर आप एक अलग दृष्टिकोण चाहते हैं। इसके अलावा, NULL'ing विदेशी प्रमुख मूल्य बाद की जटिलताओं का नेतृत्व कर सकते हैं क्योंकि आपको नहीं पता होगा कि वास्तव में वहां क्या हुआ था। तो यह परिवर्तन आपके एप्लिकेशन कोड के काम करने के संबंध में होना चाहिए।

उम्मीद है की यह मदद करेगा।


2

मुझे लार्वावेल माइग्रेशन में भी यह समस्या थी
। ड्रॉप डाउन टेबल () विधि में ड्रॉप टेबल का क्रम भी मायने रखता है

Schema::dropIfExists('groups');
Schema::dropIfExists('contact');

काम नहीं कर सकता है, लेकिन अगर आप ऑर्डर बदलते हैं, तो यह काम करता है।

Schema::dropIfExists('contact');
Schema::dropIfExists('groups');

1

यदि आपको जल्द से जल्द क्लाइंट का समर्थन करने की आवश्यकता है, और इसके लिए एक्सेस नहीं है

FOREIGN_KEY_CHECKS

ताकि डेटा अखंडता को निष्क्रिय किया जा सके:

1) विदेशी कुंजी को हटाएं

ALTER TABLE `advertisers` 
DROP FOREIGN KEY `advertisers_ibfk_1`;

2) अपने हटाने के संचालन को सक्रिय करें

3) स्कीमा में विदेशी कुंजी वापस जोड़ें

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

हालांकि, यह एक हॉट-फ़िक्स है, इसलिए यह आपके स्वयं के जोखिम पर है, क्योंकि इस तरह के दृष्टिकोण का मुख्य दोष यह है कि डेटा अखंडता को मैन्युअल रूप से रखने के लिए बाद में इसकी आवश्यकता होती है।


0

आप नौकरी हटाने से पहले संदर्भित पंक्तियों को हटाने के लिए एक ट्रिगर बना सकते हैं।

    DELIMITER $$
    CREATE TRIGGER before_jobs_delete 
        BEFORE DELETE ON jobs
        FOR EACH ROW 
    BEGIN
        delete from advertisers where advertiser_id=OLD.advertiser_id;
    END$$
    DELIMITER ;

0

इस कटाव के साथ मुख्य समस्या यह Error Code: 1451. Cannot delete or update a parent row: a foreign key constraint failsहै कि यह आपको पता नहीं होने देता कि किस तालिका में FK विफलता है, इसलिए संघर्ष को हल करना मुश्किल है।

यदि आप MySQL या इसी तरह का उपयोग करते हैं, तो मुझे पता चला कि आप अपने डेटाबेस के लिए एक ईआर आरेख बना सकते हैं , फिर आप त्रुटि को ट्रिगर करने वाले किसी भी टकराव की समीक्षा कर सकते हैं और सुरक्षित रूप से निकाल सकते हैं।

  1. MySQL कार्यक्षेत्र का उपयोग करें
  2. डेटाबेस -> रिवर्स इंजीनियरिंग पर क्लिक करें
  3. एक सही का चयन करें connection
  4. अंत तक अगला, चयन करने के लिए याद रखें databaseऔर tablesजिसे जांच की आवश्यकता है
  5. अब आपके पास ईआर आरेख है, आप देख सकते हैं कि किस तालिका में एफके संघर्ष है

0

मूल रूप से, इस प्रकार की त्रुटि के पीछे का कारण अंततः आप एक ऐसी कुंजी को हटाना चाहते हैं जिसमें प्राथमिक कुंजी (रूट टेबल) है और उस प्राथमिक कुंजी का उपयोग विदेशी तालिका में एक विदेशी कुंजी के रूप में किया जाता है। इस परिदृश्य में पैरेंट टेबल डेटा को हटाने के लिए आपको चाइल्ड टेबल डेटा (जिसमें विदेशी कुंजी का उपयोग किया जाता है) को हटाना होगा। धन्यवाद


0

यह मेरे साथ भी हुआ और अन्य तालिकाओं से निर्भरता और संदर्भ के कारण, मैं प्रविष्टि को हटा नहीं सका। मैंने जो किया था उसे टेबल पर एक डिलीट कॉलम (टाइप बूलियन) जोड़ा गया। उस फ़ील्ड का मान दिखाया गया है कि आइटम को हटाने के लिए चिह्नित किया गया है या नहीं। यदि विलोपन के लिए चिह्नित किया गया है, तो लाने / उपयोग न करें; अन्यथा, इसका उपयोग करें।


-1

शायद आपको DELETE CASCADE पर प्रयास करना चाहिए


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