INSERT में कैसे ऑटो_इन्क्रिमेंट कीज़ को हैंडल किया जाता है (Select * FROM…)


13

मेरे पास table1और table2MySQL में है। दोनों के पास एक प्राथमिक auto_incrementकुंजी है id

यदि टेबल स्कीमा मेल खाता है और मैं करता हूं INSERT INTO table1 (SELECT * FROM table2)कि नई पंक्तियों के संबंध में क्या होता है table1? क्या वे अपने पुराने idमूल्यों को बनाए रखते हैं और जब एक पंक्ति table1समान होती है, तो वे संघर्ष पैदा करते हैं id? Auto_increment द्वारा नए मान उत्पन्न किए गए हैं? क्या यह भंडारण इंजन या लॉकिंग पर निर्भर करता है?

जवाबों:


13

आप एक ऑटो-इंक्रीमेंट कॉलम में सम्मिलित कर सकते हैं और एक मूल्य निर्दिष्ट कर सकते हैं। यह ठीक है; यह बस ऑटो-इन्क्रीमेंट जनरेटर को ओवरराइड करता है।

यदि आप NULL या 0 का मान सम्मिलित करने का प्रयास करते हैं DEFAULT, या यदि आप अपने INSERT कथन में कॉलम से ऑटो-इंक्रीमेंट कॉलम को छोड़ते हैं, तो यह ऑटो-इन्क्रीमेंट जनरेटर को सक्रिय करता है।

तो, यह ठीक है INSERT INTO table1 SELECT * FROM table2(वैसे, आपको कोष्ठकों की आवश्यकता नहीं है)। इसका मतलब यह है कि आईडी मानों को table2शब्दशः कॉपी किया जाएगा, और नए मान उत्पन्न नहींtable1 होंगे ।

यदि आप नए मान उत्पन्न करना चाहते table1 हैं, तो आप ऐसा नहीं कर सकते SELECT *। या तो आप आईडी कॉलम के लिए null या 0 का उपयोग करते हैं:

INSERT INTO table1 SELECT 0, col1, col2, col3, ... FROM table2;

या फिर आप INSERT स्टेटमेंट की कॉलम सूची और SELECT स्टेटमेंट की चयन सूची दोनों से कॉलम को छोड़ देते हैं:

-- No id in either case:
INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3, ... FROM table2;

आपके पूछने से पहले, "एक कॉलम को छोड़कर" का चयन करने के लिए SQL में कोई सिंटैक्स नहीं है। आपको उन स्तंभ नामों की पूरी सूची स्पेल करनी होगी जिन्हें आप सम्मिलित करना चाहते हैं।


क्या कोई विकल्प नहीं है जो 0 / मान को डालने की अनुमति देता है? (अपने दूसरे पैराग्राफ के बारे में)
साशा रामबाईद

1
हाँ, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , अन्यथा हम कभी भी AI कॉलम में शाब्दिक शून्य मान नहीं डाल सकते। यदि आप इस SQL ​​मोड का उपयोग करते हैं, तो NULL अभी भी AI जनरेटर को सक्रिय करने के लिए काम करता है, या स्तंभ कार्य को छोड़ देता है।
बिल कार्विन

@BillKarwin, अपने आखिरी पैराग्राफ के बारे में, सबरेल्ट प्राप्त करने के बाद select * from table, क्या इस सबसॉल्ट पर अपने पहले कॉलम को हटाने का कोई तरीका नहीं है?
पचेरियर

@ स्पेसियर, अगर मैं सही तरीके से समझूं, तो आप पूछ select *सकते हैं कि क्या इसका मतलब हो सकता है select * except for the first column। जवाब न है। select *हमेशा उस तालिका से सभी स्तंभों का अनुरोध करता है । यदि आप एक सबसेट चाहते हैं, तो आपको अपने इच्छित कॉलमों को वर्तनी में बदल देना चाहिए।
बिल करविन

@ बिलकर्विन, हम्म, मैं ऊर्ध्वाधर जहां करने के लिए टेबल को पिवट करने के बारे में सोच रहा था , फिर इसे वापस ला रहा हूं जैसे कि select*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)या शायद अधिक रसीला रूप में select*from table where Id=1 and $col<>Id, आप क्या सोचते हैं?
5

3

चयन से आईडी तालिका में सम्मिलित समान मूल्य होगा। यदि आप मौजूदा पंक्तियों को डुप्लिकेट करने का प्रयास कर रहे हैं, तो यह त्रुटि होगी।

बिल कारविन: इससे पहले कि आप पूछें, "एक कॉलम को छोड़कर" का चयन करने के लिए SQL में कोई सिंटैक्स नहीं है।

यह कुछ रचनात्मकता के साथ प्राप्त किया जा सकता है:

SET @sql = CONCAT('INSERT INTO <table> SELECT null, 
    ', (SELECT GROUP_CONCAT(COLUMN_NAME) 
    FROM information_schema.columns 
    WHERE table_schema = '<database>' 
    AND table_name = '<table>' 
    AND column_name NOT IN ('id')), ' 
from <table> WHERE id = <id>');  

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

इससे नई पंक्ति में चयनित पंक्ति से आईडी के बजाय एक ऑटो इंक्रीमेंट आईडी प्राप्त होगी।


2
चतुर, लेकिन मेरे लिए, जो आपके द्वारा सम्मिलित किए जाने वाले स्तंभ नामों की पूरी सूची वर्तनी के रूप में गिना जाता है।
बिल कार्विन

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