विदेशी कुंजी संदर्भात्मक कार्रवाई कैसे बदलें? (व्यवहार)


102

मैंने एक तालिका स्थापित की है जिसमें एक विदेशी कुंजी वाला एक कॉलम है, जिसे ON DELETE CASCADEमाता-पिता द्वारा हटाए जाने पर बच्चे को हटा दें)

इसे बदलने के लिए SQL कमांड क्या होगा ON DELETE RESTRICT? (यदि बच्चे हैं तो माता-पिता को नहीं हटा सकते)

जवाबों:


170

पुराना सवाल है लेकिन जवाब जोड़ रहे हैं ताकि किसी को मदद मिल सके

इसकी दो चरण प्रक्रिया:

मान लीजिए, स्तंभ नाम के साथ table1एक विदेशी कुंजी हैfk_table2_id , बाधा नाम के साथ है fk_nameऔर table2इसे कुंजी t2( मेरे आरेख में नीचे की तरह कुछ ) के साथ तालिका में संदर्भित किया गया है ।

   table1 [ fk_table2_id ] --> table2 [t2]

पहला कदम , पुराना विरोध: ( संदर्भ )

ALTER TABLE `table1` 
DROP FOREIGN KEY `fk_name`;  

सूचना बाधा हटा दी गई है, स्तंभ हटाया नहीं गया है

दूसरा चरण , नए अनुबंध जोड़ें:

ALTER TABLE `table1`  
ADD CONSTRAINT `fk_name` 
    FOREIGN KEY (`fk_table2_id`) REFERENCES `table2` (`t2`) ON DELETE CASCADE;  

बाधा जोड़ने, स्तंभ पहले से ही है

उदाहरण:

मेरे पास एक UserDetailsटेबल है टेबल को संदर्भित करता है Users:

mysql> SHOW CREATE TABLE UserDetails;
:
:
 `User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`)
:
:

पहला कदम:

mysql> ALTER TABLE `UserDetails` DROP FOREIGN KEY `FK_User_id`;
Query OK, 1 row affected (0.07 sec)  

दूसरा कदम:

mysql> ALTER TABLE `UserDetails` ADD CONSTRAINT `FK_User_id` 
    -> FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`) ON DELETE CASCADE;
Query OK, 1 row affected (0.02 sec)  

परिणाम:

mysql> SHOW CREATE TABLE UserDetails;
:
:
`User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES 
                                       `Users` (`User_id`) ON DELETE CASCADE
:

2
मूल प्रश्न के अनुरोध के अनुसार आपके द्वारा जोड़ा गया अवरोध नहीं होना चाहिए?
नूमेनन

एहम, "डिलीट कैस्केड पर" क्या है और यह क्यों है?
एलो

3
@Noumenon RESTRICT डिफ़ॉल्ट है इसलिए आपको यह निर्दिष्ट करना है कि कब निर्दिष्ट नहीं किया जाए।
एड्रिड

1
@Lealo "डिलीट कैस्केड पर" का अर्थ है कि यदि आप पेरेंट टेबल से एक पंक्ति हटाते हैं (उपयोगकर्ता इस मामले में) तो चाइल्ड टेबल (UserDetails) से सभी संदर्भित पंक्तियों को भी हटा दिया जाता है।
एड्रिड

1
नोटों के लिए धन्यवाद "नोटिस बाधा हटा दिया गया है, कॉलम हटा नहीं है", "बाधा जोड़ रहा है, स्तंभ पहले से ही है", अनुमान है कि डेटा व्यावहारिक रूप से संरक्षित है और केवल स्कीमा में परिवर्तन होता है
जॉर्ज बिरबिलिस

21

यदि आप इसका नाम बदलना चाहते हैं तो आप इसे एक क्वेरी में कर सकते हैं :

ALTER TABLE table_name
  DROP FOREIGN KEY `fk_name`,
  ADD CONSTRAINT `fk_name2` FOREIGN KEY (`remote_id`)
    REFERENCES `other_table` (`id`)
    ON DELETE CASCADE;

यदि आपके पास एक बड़ी तालिका है, तो डाउनटाइम को कम करने के लिए यह उपयोगी है।


12
ALTER TABLE DROP FOREIGN KEY fk_name;
ALTER TABLE ADD FOREIGN KEY fk_name(fk_cols)
            REFERENCES tbl_name(pk_names) ON DELETE RESTRICT;

2
मुझे इसका हल खोजने में मदद की ALTER TABLE table_name ADD...ON DELETE RESTRICT
Moak

3
नहीं, fk_name बाधा नाम है। यह एक प्रदान करने के लिए वैकल्पिक है। मुझे यकीन नहीं है, लेकिन शायद आप इसका उपयोग करके पुनः प्राप्त कर सकते हैं SHOW CREATE TABLE
पास्कल

1
CASCADE RESTRICT पर शायद इरादा नहीं है।
jgreep

5

याद रखें कि MySQL विदेशी कुंजी को हटाने के बाद एक कॉलम पर एक सरल सूचकांक रखता है। इसलिए, यदि आपको 'संदर्भ' कॉलम बदलने की आवश्यकता है, तो आपको इसे 3 चरणों में करना चाहिए

  • मूल FK छोड़ें
  • एक इंडेक्स ड्रॉप करें (पिछले fk के रूप में नाम, drop indexक्लॉज का उपयोग करके )
  • नया FK बनाएं

3

आप बस उन सभी पर शासन करने के लिए एक क्वेरी का उपयोग कर सकते हैं: ALTER TABLE products DROP FOREIGN KEY oldConstraintName, ADD FOREIGN KEY (product_id, category_id) REFERENCES externalTableName (foreign_key_name, another_one_makes_composite_key) ON DELETE CASCADE ON UPDATE CASCADE


1
यह केवल तभी काम करेगा जब आप बाधा नाम बदलेंगे (यदि ऑटो-जेनरेट नाम का उपयोग करते हैं तो शायद यह काम करेगा, अनुमान करें कि MySQL हमेशा अद्वितीय बनाता है)
जॉर्ज बिरबिलिस

क्वेरी MySQL / MariaDB पर निश्चित रूप से काम करती है। यहां कुंजी पुराने नाम से गिराने के लिए है, जो कि नाम 2 है, जो कि लाइन 2 पर किया जा रहा है
स्टैमस्टर

1
ऑल-इन-वन क्वेरी सिंटैक्स ने MySQL के साथ मेरे लिए काम नहीं किया जब स्पष्ट बाधा नाम का उपयोग किया गया था
जॉर्ज बीरबिलिस

3

मेरे पास फेरबदल करने के लिए एफके का एक गुच्छा था, इसलिए मैंने मेरे लिए बयान करने के लिए कुछ लिखा। मुझे लगा कि मैं साझा करूंगा:

SELECT

CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` DROP FOREIGN KEY `' ,rc.CONSTRAINT_NAME,'`;')
, CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` ADD CONSTRAINT `' ,rc.CONSTRAINT_NAME ,'` FOREIGN KEY (`',kcu.COLUMN_NAME,
    '`) REFERENCES `',kcu.REFERENCED_TABLE_NAME,'` (`',kcu.REFERENCED_COLUMN_NAME,'`) ON DELETE CASCADE;')

FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
LEFT OUTER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
    ON kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
    AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
WHERE DELETE_RULE = 'NO ACTION'
AND rc.CONSTRAINT_SCHEMA = 'foo'

1
यदि एक बाधा कई स्तंभों पर है, तो यह काम नहीं करेगा। उत्पन्न चक्र प्रत्येक कॉलम के लिए अलग-अलग अवरोध पैदा करेगा
रोशनी

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