2009-04-22 21 views
104

मेरे पास निम्न क्वेरी है:MySQL ऑन डिप्लिकेट कुंजी - अंतिम डालने आईडी?

INSERT INTO table (a) VALUES (0) 
    ON DUPLICATE KEY UPDATE a=1 

मैं या तो सम्मिलित या अद्यतन की आईडी चाहता हूं। आमतौर पर मैं इसे प्राप्त करने के लिए दूसरी क्वेरी चलाता हूं क्योंकि मेरा मानना ​​है कि insert_id() केवल 'डाली गई' आईडी लौटाता है, न कि अद्यतन आईडी।

क्या INSERT/UPDATE का कोई तरीका है और दो प्रश्नों को चलाने के बिना पंक्ति की आईडी पुनर्प्राप्त करें?

+3

मानने की बजाय, आप इसे स्वयं परीक्षण क्यों नहीं करते? उपरोक्त संपादन में एसक्यूएल काम करता है, और मेरे परीक्षण के माध्यम से एक प्रविष्टि विफल होने से तेज है, INSERT IGNORE का उपयोग करके, या यह देखने के लिए कि पहले डुप्लिकेट है या नहीं। –

+1

चेतावनी: समाधान प्रस्तावित काम करता है, लेकिन auto_increment मान में वृद्धि जारी है, भले ही कोई सम्मिलित न हो। यदि डुप्लिकेट कुंजी अक्सर होती है, तो आप उपरोक्त क्वेरी के बाद 'तालिका तालिका टैबलेटनाम AUTO_INCREMENT = 0;' को अपने आईडी मानों में बड़े अंतर से बचने के लिए चला सकते हैं। –

उत्तर

125

चेक यह पेज बाहर सुधारा: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
पृष्ठ के तल पर वे बताती हैं कि एक अभिव्यक्ति गुजर th करने से अद्यतन के लिए LAST_INSERT_ID सार्थक बना सकते हैं MySQL फ़ंक्शन पर।

MySQL प्रलेखन उदाहरण से:

एक मेज एक AUTO_INCREMENT कॉलम होता है और सम्मिलित करें ... अद्यतन एक पंक्ति सम्मिलित करता है, तो LAST_INSERT_ID() फ़ंक्शन AUTO_INCREMENT मान देता है। यदि कथन इसके बजाय एक पंक्ति अद्यतन करता है, तो LAST_INSERT_ID() सार्थक नहीं है। हालांकि, आप LAST_INSERT_ID (expr) का उपयोग कर इसके आसपास काम कर सकते हैं। मान लें कि आईडी AUTO_INCREMENT कॉलम है। LAST_INSERT_ID() अद्यतन के लिए सार्थक बनाने के लिए, सम्मिलित पंक्तियों इस प्रकार है:

INSERT INTO table (a,b,c) VALUES (1,2,3) 
    ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3; 
+2

किसी भी तरह से मुझे याद आया कि उस पृष्ठ को देखते समय। तो अद्यतन भाग के रूप में प्रकट होता है: अद्यतन आईडी = LAST_INSERT_ID (आईडी) और वह अच्छा काम करता है। धन्यवाद! – thekevinscott

+1

खुशी है कि मैं मदद कर सकता हूँ! – fredrik

+6

ऐसा कहा जाता है कि php function mysql_insert_id() दोनों मामलों में सही मान देता है: http://www.php.net/manual/en/function.mysql-insert-id.php#59718। – jayarjo

2

आप रेप्लेस देख सकते हैं, जो रिकॉर्ड मौजूद होने पर अनिवार्य रूप से एक डिलीट/डालने वाला है। लेकिन यदि वर्तमान में ऑटो वृद्धि क्षेत्र बदल जाएगा, जो अन्य डेटा के साथ संबंध तोड़ सकता है।

+1

आह हाँ - मैं ऐसा कुछ ढूंढ रहा हूं जो पिछली आईडी के – thekevinscott

+0

से छुटकारा नहीं पायेगा यह खतरनाक भी हो सकता है क्योंकि यह किसी अन्य संबंधित डेटा (बाधाओं से) को भी हटा सकता है। – Serge

0

यह ध्यान देने योग्य है, और इस स्पष्ट हो सकता है (लेकिन मैं यहाँ स्पष्टता के लिए वैसे भी यह कहूँगा), कि REPLACE दूर उड़ा होगा अपना नया डेटा डालने से पहले मौजूदा मिलान पंक्ति। डिप्लिकेट कुंजी अपडेट केवल आपके द्वारा निर्दिष्ट कॉलम अपडेट करेगा और पंक्ति को संरक्षित करेगा।

manual से

:

REPLACE काम करता है वास्तव में सम्मिलित करें, की तरह, सिवाय इसके कि टेबल में एक पुराने पंक्ति एक प्राथमिक कुंजी या एक अद्वितीय सूचकांक, के लिए एक नई पंक्ति जितना समान मान है, तो नई पंक्ति डालने से पहले पुरानी पंक्ति हटा दी गई है।

25

सटीक होना करने के लिए, अगर यह मूल प्रश्न है:

INSERT INTO table (a) VALUES (0) 
    ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), a=1 
:

INSERT INTO table (a) VALUES (0) 
ON DUPLICATE KEY UPDATE a=1 

और 'आईडी' ऑटो वेतन वृद्धि इस से प्राथमिक कुंजी काम कर समाधान होगा

सब यहाँ है: एक मेज एक AUTO_INCREMENT शामिल http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

हैं कॉलम और INSERT ... अद्यतन एक पंक्ति डालें, LAST_INSERT_ID() फ़ंक्शन AUTO_INCREMENT मान देता है। यदि कथन के बजाय एक पंक्ति अद्यतन करता है, LAST_INSERT_ID() सार्थक नहीं है। हालांकि, आप LAST_INSERT_ID (expr) का उपयोग करके इस के आसपास काम कर सकते हैं। मान लीजिए कि आईडी AUTO_INCREMENT कॉलम है।

+3

हां, आपने जो कहा है उसके लिए स्वीकृत उत्तर देखें। 3 साल पुरानी पोस्ट को पुनर्जीवित करने की कोई जरूरत नहीं है। वैसे भी आपके प्रयास के लिए धन्यवाद। – fancyPants

+1

@ टॉम्बॉम एकमात्र कारण है कि मैंने यह जवाब क्यों पोस्ट किया है क्योंकि स्वीकृत उत्तर सही नहीं है - अगर अपडेट करने के लिए कुछ भी नहीं है तो यह काम नहीं करेगा। –

+0

+1 हालांकि मुझे लगता है कि स्वीकृत उत्तर का उल्लेख है कि :) – fancyPants

0

यदि आप ऑटोइनक्रिकमेंट का उपयोग करते हैं तो मौजूदा समाधान काम करते हैं। मेरे पास एक ऐसी स्थिति है जहां उपयोगकर्ता उपसर्ग को परिभाषित कर सकता है और इसे 3000 पर अनुक्रम को पुनरारंभ करना चाहिए। इस विविध उपसर्ग के कारण, मैं autoincrement का उपयोग नहीं कर सकता, जो अंतिम_insert_id को आवेषण के लिए खाली बनाता है। मैं निम्नलिखित के साथ इसे हल: उपसर्ग मौजूद

INSERT INTO seq_table (prefix, id) VALUES ('$user_prefix', LAST_INSERT_ID(3000)) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id + 1); 
SELECT LAST_INSERT_ID(); 

, तो इसे बढ़ाने के और last_insert_id बस जाएँगे। यदि उपसर्ग मौजूद नहीं है, तो यह 3000 के साथ उपसर्ग को सम्मिलित करेगा और 3000 के साथ last_insert_id को पॉप्युलेट करेगा।

संबंधित मुद्दे