एक विदेशी कुंजी बाधा में उपयोग किए गए कॉलम को बदल नहीं सकते


111

मुझे यह त्रुटि तब मिली जब मैं अपनी तालिका को बदलने की कोशिश कर रहा था।

Error Code: 1833. Cannot change column 'person_id': used in a foreign key constraint 'fk_fav_food_person_id' of table 'table.favorite_food'

यहाँ मेरा CREATE TABLE STATEMENT है जो सफलतापूर्वक चला।

CREATE TABLE favorite_food(
    person_id SMALLINT UNSIGNED,
    food VARCHAR(20),
    CONSTRAINT pk_favorite_food PRIMARY KEY(person_id,food),
    CONSTRAINT fk_fav_food_person_id FOREIGN KEY (person_id)
    REFERENCES person (person_id)
);

तब मैंने इस कथन को निष्पादित करने की कोशिश की और मुझे उपरोक्त त्रुटि मिली।

ALTER TABLE person MODIFY person_id SMALLINT UNSIGNED AUTO_INCREMENT;

4
उपरोक्त उदाहरण "लर्निंग एसक्यूएल, 2 डी संस्करण" पुस्तक से है। मुझे आशा है कि लेखक, एलन ब्यूलियू सुधार करता है।
दिमित्री

जवाबों:


126

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

एक समाधान यह होगा:

LOCK TABLES 
    favorite_food WRITE,
    person WRITE;

ALTER TABLE favorite_food
    DROP FOREIGN KEY fk_fav_food_person_id,
    MODIFY person_id SMALLINT UNSIGNED;

अब आप बदल सकते हैं person_id

ALTER TABLE person MODIFY person_id SMALLINT UNSIGNED AUTO_INCREMENT;

विदेशी कुंजी को पुनः बनाएँ

ALTER TABLE favorite_food
    ADD CONSTRAINT fk_fav_food_person_id FOREIGN KEY (person_id)
          REFERENCES person (person_id);

UNLOCK TABLES;

संपादित करें: ऊपर दिए गए ताले, टिप्पणियों के लिए धन्यवाद

ऐसा करते समय आपको डेटाबेस को लिखना बंद करना होगा, अन्यथा आप डेटा अखंडता समस्याओं का जोखिम उठाते हैं।

मैंने ऊपर एक राइट लॉक जोड़ा है

आपके ( INSERT, UPDATE, DELETE) के अलावा किसी भी अन्य सत्र में सभी लेखन क्वेरीज़ समय-सीमा तक प्रतीक्षा करेंगी या UNLOCK TABLES; निष्पादित किया जाता है

http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html

EDIT 2: ओपी ने रेखा के बारे में और अधिक विस्तृत विवरण के लिए कहा "विदेशी कुंजी क्षेत्र और संदर्भ की परिभाषा और परिभाषा बराबर होनी चाहिए। इसका मतलब है कि आपकी विदेशी कुंजी आपके क्षेत्र के प्रकार को बदल रही है।"

से विदेशी कुँजी प्रतिबंध: MySQL 5.5 संदर्भ मैनुअल

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


1
इसके लिए लेनदेन का उपयोग करना न भूलें। अन्यथा आपका डेटाबेस दूषित हो सकता है।
फ्रेंकोइस बुर्जुआ 14

5
अच्छी बात है, दुर्भाग्यवश MySQL DDL स्टेटमेंट्स के आसपास लेनदेन का समर्थन नहीं करता है। DDL क्वेरी निष्पादित होने से पहले खुले लेन-देन शुरू हो जाते हैं dev.mysql.com/doc/refman/5.5/en/implicit-commit.html
मिशेल

2
एक विदेशी कुंजी को फिर से बनाने के लिए सही कथन होगा: ALTER TALE पसंदीदा_फूड ADD CONTRAINT fk_fav_food_person_id FOREIGN KEY (person_id) संदर्भ व्यक्ति (आईडी);
फेलिडेरिको

1
person_idविदेशी कुंजी छोड़ने के बाद आप सही संशोधित क्यों करते हैं ? ऐसा लगता है जैसे आपने पहले से ही कुछ भी नहीं बदला है SMALLINT UNSIGNED
डेनिस सुबचेव

1
हमें नहीं पता कि यह क्या था क्योंकि उन्होंने केवल संदर्भित तालिका संरचना पोस्ट की थी। इनोडब में आंतरिक प्रकार के रूप में int है, smallint आदि केवल शॉर्टकट हैं
मिशेल

198

आप विदेशी कुंजी चेक बंद कर सकते हैं:

SET FOREIGN_KEY_CHECKS = 0;

/* DO WHAT YOU NEED HERE */

SET FOREIGN_KEY_CHECKS = 1;

कृपया उत्पादन पर इसका उपयोग न करें और बैकअप लें।


1
बहुत असुरक्षित समाधान लगता है। क्या यह संभवतः डेटा अखंडता के नुकसान का कारण बन सकता है?
1

@ साइन - यदि आप हटा रहे हैं / अद्यतन / सम्मिलित कर रहे हैं, तो यह हाँ। डेटा हानि करता है, तो आप सिर्फ एक मेज संशोधित कर रहे हैं या अपने डाटाबेस बोने, दूसरे हाथ आप अपने डेटा को मैन्युअल सत्यापित करना चाहिए (जब से तुम कमी निकालने के लिए) पर घटित नहीं होगा
Dementic

2
यह समाधान बहुत अच्छा है, और यदि आप अपने डेटा को संशोधित करने से पहले ताले लिखते हैं और जब आप काम करते हैं तो एक अनलॉक होने पर आप इसका उपयोग उत्पादन पर कर सकते हैं। कम से कम समय में अपने परिवर्तनों को करने के लिए एक sql फ़ाइल का उपयोग करना और भी बेहतर होगा।
17:46 पर फ्रांसिस्को ज़ाराबोज़ो

तेजी से मरोड़ के लिए अच्छा उपाय
Genaut

1
आपको SET FOREIGN_KEY_CHECKSसत्र-स्कोप के रूप में लॉक की आवश्यकता नहीं है (अन्य सत्रों में अभी भी एफके बाधा लागू होगी)। यह हटाने के जोड़ने / के लिए एकदम सही AUTO_INCREMENTहै (जो वास्तविक स्तंभ डेटाप्रकार परिवर्तन नहीं करता है), लेकिन यह काम नहीं करेगा आप के लिए 'असली' (जैसे कि, SMALLINT से INT करने के लिए) के रूप में आप एक वैध मिलेगा स्तंभ डेटाप्रकार बदलने की कोशिश करता है, तो 150 FK constraint incorrectly formedजब mysql पुरानी तालिका को नए से बदलने की कोशिश करता है। ऐसे मामले में, स्वीकृत उत्तर का उपयोग करें।
एक्सनोस २

-3

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


12
यह वह जगह है ऐसी एक बेकार, बेकार जवाब!
अंजडवे

3
@ajmedway तब आप अन्य उपयोगकर्ताओं को दोषी ठहराए बिना एक उपयोगी उत्तर लिख सकते हैं
मैं सबसे मूर्ख व्यक्ति हूं

2
@IamtheMostStupidPerson यह सिर्फ एक टिप्पणी के बिना downvoting से बेहतर है। कम से कम टिप्पणीकार अनुमान लगा सकता है कि नीचे की ओर क्यों। इस तरह के जेनेरिक जवाब "सॉरी से बेहतर रहें" उपयोगी नहीं हैं।
Csaba टोथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.