MySQL: स्वत: संदर्भित शून्य, auto_increment, विदेशी कुंजी नहीं?

क्या यह MySQL (किसी भी संस्करण में) को घोषित करने और एक सारणी के साथ एक तालिका का उपयोग करने के लिए संभव है, न कि शून्य, विदेशी कुंजी कॉलम एक ही तालिका की स्वत: क्रिकमेंट प्राथमिक कुंजी का जिक्र है?

अनिवार्य रूप से, मैं निम्नलिखित तालिका बनाना चाहता हूं, जिसमें पंक्तियां पेड़ के जंगल का प्रतिनिधित्व करती हैं। मुझे पदानुक्रम में रूट नोड्स को id के बराबर पंक्ति के parent_id द्वारा इंगित किया जाना चाहिए (NULL को parent_id रूट इंगित करने के लिए)।

जैसे

CREATE TABLE forest (
    id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    parent_id BIGINT NOT NULL,
        CONSTRAINT fk_forest_parent_id FOREIGN KEY(parent_id) REFERENCES forest(id),
    name VARCHAR(20) NOT NULL UNIQUE
);

इस तालिका को बनाना (5.0.44sp1-enterprise-gpl-nt-log MySQL एंटरप्राइज़ सर्वर (जीपीएल) काम करता है)। हालांकि रूट नोड्स के parent_id को सम्मिलित करने के लिए LAST_INSERT_ID() का उपयोग करना संभव नहीं लगता है (जो आश्चर्य की बात नहीं है)। उदाहरण के लिए निम्नलिखित काम नहीं करता है:

INSERT INTO forest(parent_id, name) VALUES (LAST_INSERT_ID(), "root 1");

निम्नलिखित काम करता है, लेकिन अब ऑटो वृद्धि का उपयोग नहीं कर रहा है:

INSERT INTO forest(id, parent_id, name) VALUES (1234, 1234, "root 1");

क्या इस तरह से परिभाषित एक तालिका का उपयोग करने का कोई तरीका है, जबकि अभी भी स्वचालित रूप से जेनरेट किए गए पीके पर भरोसा है, और साथ ही सभी बाधाओं को भी बनाए रखना है (न्यूल, और विदेशी कुंजी)?

अद्यतन - संभावित समाधान:

START TRANSACTION;
SET FOREIGN_KEY_CHECKS = 0;
INSERT INTO forest(parent_id, name) VALUES (0, "root X");
UPDATE forest SET parent_id = LAST_INSERT_ID() WHERE id = LAST_INSERT_ID();
SET FOREIGN_KEY_CHECKS = 1; /* This seems to be important. */
COMMIT;
2
इस तरह की चाबियों में कुछ भी गलत नहीं है। लेकिन उसी कोड में LAST_INSERT_ID() का उपयोग करके जहां आईडी जेनरेट की जा रही है, स्पष्ट रूप से काम नहीं करेगी।
जोड़ा लेखक Álvaro González, स्रोत
माता-पिता को बेकार छोड़ दें। यदि आप चाहते हैं कि यह आईडी के समान मूल्य हो, तो आप एक गणना कॉलम गंभीर_this_parent_id को Coalesce (parent_id, id) के रूप में जोड़ सकते हैं
जोड़ा लेखक gvee, स्रोत

1 उत्तर

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

INSERT INTO forest(name) VALUES ("root 1");
UPDATE forest SET parent_id = LAST_INSERT_ID() WHERE id = LAST_INSERT_ID();

मुझे नहीं लगता कि रूट रूट नोड के लिए खुद को माता-पिता के रूप में संदर्भित करना समझ में आता है। बस केह रहा हू।

2
जोड़ा
@ पॉल मैंने इसके बारे में नहीं सोचा था। आप या तो parent_id nullable (जिसे आप शायद टालना चाहते हैं) बना सकते हैं या इसे 0 पर सेट कर सकते हैं
जोड़ा लेखक Explosion Pills, स्रोत
@ पॉल का मतलब है कि आपको किसी प्रकार का उत्पत्ति नोड होना चाहिए जिसमें id 0 है, या आप SET FOREIGN_KEY_CHECKS = 0 लेनदेन के लिए
जोड़ा लेखक Explosion Pills, स्रोत
@Paul आप parent_id को सही तरीके से सेट करने से पहले क्यों COMMIT करेंगे?
जोड़ा लेखक Explosion Pills, स्रोत
@ पॉल यह कनेक्शन के लिए बंद रहेगा। यह स्पष्ट नहीं करने के लिए खेद है। हालांकि यह सिर्फ प्रति कनेक्शन है (यानी यह उन्हें पूरी तरह से अक्षम नहीं करता है)
जोड़ा लेखक Explosion Pills, स्रोत
कोशिश की कि (स्टार्ट ट्रांज़ेक्शन के अंदर ... COMMIT)। त्रुटि: फ़ील्ड 'parent_id' के साथ विफलता डिफ़ॉल्ट मान नहीं है
जोड़ा लेखक Paul, स्रोत
Btw। मुझे लगता है कि 'पीके == एफके का मतलब है' दोनों का उपयोग करना उचित लगता है क्योंकि लगभग सभी नोड्स do में माता-पिता हैं (इसलिए न्यूल नहीं) और विशेष रूप से - क्योंकि रूट नोड्स वास्तव में जा रहे हैं पूर्व-निर्मित और स्थायी रूप से एक मूल प्रकार (अलग-अलग तालिका) के स्वामित्व में होना चाहिए। [यह सब जावा डेटा एक्सेस लेयर के नीचे हो रहा है जो मैं काम कर रहा हूं।]
जोड़ा लेखक Paul, स्रोत
parent_id को 0 पर सेट नहीं किया जा सकता - यह एक विदेशी कुंजी है। त्रुटि: कोई बाल पंक्ति जोड़ या अपडेट नहीं कर सकता: एक विदेशी कुंजी बाधा विफल हो जाती है (वन, CONSTRAINT fk_forest_parent_id विदेशी कुंजी (parent_id) संदर्भ वन (आईडी))
जोड़ा लेखक Paul, स्रोत
दिलचस्प। मुझे नहीं पता था कि आप ऐसा कर सकते हैं। (हालांकि, ऐसा प्रतीत होता है, एफके बाधा लागू नहीं है यहां तक ​​कि COMMIT - यानी मेरे पास अब मेरे उदाहरण डीबी में डेटा है जो मेरे डेटाबेस की बाधाओं का उल्लंघन करता है!)
जोड़ा लेखक Paul, स्रोत
इसके अलावा, 'उत्पत्ति नोड' द्वारा मैं अनुमान लगा रहा हूं कि आप किसी प्रकार का 'ब्रह्मांड की जड़' नोड का अर्थ है जो अन्य सभी (रूट) नोड्स के 'माता-पिता' के रूप में होते हैं। (लेकिन तब उस नोड को parent_id होना चाहिए - उपरोक्त बाधाओं को देखते हुए - इसलिए मुझे यकीन नहीं है कि कहीं भी उपयोग किया जाए।)
जोड़ा लेखक Paul, स्रोत
मैंने नहीं किया - मैंने बाद में किया। ऐसा लगता है कि TX के अंत से पहले SET FOREIGN_KEY_CHECKS = 1 स्पष्ट रूप से आवश्यक है; अन्यथा यह कम से कम उस कनेक्शन के लिए रहें बंद होता है (मुझे लगता है कि यह नहीं होगा)।
जोड़ा लेखक Paul, स्रोत
जोड़ा लेखक Paul, स्रोत