डुप्लिकेट कुंजी अद्यतन पर समान सम्मिलित करें


158

मैंने आसपास खोज की है, लेकिन अगर यह संभव है तो नहीं मिला।

मैंने यह MySQL क्वेरी:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)

फ़ील्ड आईडी में एक "अद्वितीय सूचकांक" होता है, इसलिए उनमें से दो नहीं हो सकते। अब यदि वही आईडी डेटाबेस में पहले से मौजूद है, तो मैं इसे अपडेट करना चाहूंगा। लेकिन क्या मुझे वास्तव में इन सभी क्षेत्रों को फिर से निर्दिष्ट करना होगा, जैसे:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY UPDATE a=2,b=3,c=4,d=5,e=6,f=7,g=8

या:

INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY UPDATE a=VALUES(a),b=VALUES(b),c=VALUES(c),d=VALUES(d),e=VALUES(e),f=VALUES(f),g=VALUES(g)

मैंने पहले से ही सब कुछ डालने में निर्दिष्ट किया है ...

एक अतिरिक्त नोट, मैं आईडी प्राप्त करने के लिए चारों ओर काम का उपयोग करना चाहूंगा!

id=LAST_INSERT_ID(id)

मुझे उम्मीद है कि कोई मुझे बता सकता है कि सबसे कुशल तरीका क्या है।


9
AFAIK, प्रत्येक स्तंभ को पुनर्स्थापित करने की विधि, a=VALUES(a), b=VALUES(b), ...जिस तरह से आपको जाने की आवश्यकता है। मैं अपने सभी INSERT ON DUPLICATE KEY UPDATEकथनों के लिए यह कैसे करता हूं ।
वल्दोग्ग 21

4
बस स्पष्ट करने के लिए, यहां बताई गई हर बात सही है जब तक आप समझे गए प्रश्न का उत्तर दिया जा रहा है: क्या आपको हर उस कॉलम को पुनर्स्थापित करना चाहिए जिसे आप अपडेट करना चाहते हैं? हां, यदि आप 25-कॉलम तालिका में 8 कॉलम सम्मिलित करना या अपडेट करना चाहते हैं, तो आपको सम्मिलित भाग में एक बार और अद्यतन भाग में एक बार 8 कॉलम दो बार बताना होगा। (आप अद्यतन हिस्से में प्राथमिक कुंजी को छोड़ सकते हैं, लेकिन "a = 1, b = 2, c = 3" स्ट्रिंग को पूर्ववत करना और इसे दो बार एम्बेड करना सबसे आसान है।) हालांकि, आपको शेष 17 कॉलम को पुनर्स्थापित करने की आवश्यकता नहीं है। आप बदलना नहीं चाहते हैं। यदि यह अद्यतन हो जाता है, तो वे अपने मौजूदा मूल्यों को बनाए रखेंगे।
टिम्बरलाइन

3
मैंने उस टिप्पणी को जोड़ा क्योंकि प्रश्न और उत्तर ने मुझे इस तरह के INSERT के साथ असंबद्ध कॉलम के बारे में अनिश्चित छोड़ दिया, जिसे मैंने परीक्षण किया कि वास्तव में क्या परीक्षण करना है। INUPERT ON DUPLICATE KEY UPDATE अपरिवर्तित स्तंभों को UPDATE पर अपरिवर्तित छोड़ देता है, लेकिन उन्हें INSERT पर डिफ़ॉल्ट मान देता है। REPLACE INTO के साथ, असंबद्ध कॉलम को हमेशा डिफ़ॉल्ट मान मिलता है, कभी भी मौजूदा मान नहीं।
टिम्बरलाइन

1
Check stackoverflow.com/questions/2472229/… , मुझे लगता है कि आप वही हैं जो आप देख रहे हैं
Chococroc

जवाबों:


82

UPDATEबयान इतना है कि बड़े क्षेत्रों नया मान को अद्यतन किया जा सकता दिया जाता है। यदि आपके पुराने मूल्य आपके नए समान हैं, तो आपको इसे किसी भी मामले में अपडेट करने की आवश्यकता क्यों होगी?

उदाहरण के लिए। अपने कॉलम अगर aकरने के लिए gपहले से ही के रूप में स्थापित कर रहे हैं 2करने के लिए 8; इसे फिर से अपडेट करने की कोई आवश्यकता नहीं होगी।

वैकल्पिक रूप से, आप उपयोग कर सकते हैं:

INSERT INTO table (id,a,b,c,d,e,f,g)
VALUES (1,2,3,4,5,6,7,8) 
ON DUPLICATE KEY
    UPDATE a=a, b=b, c=c, d=d, e=e, f=f, g=g;

प्राप्त करने के लिए idसे LAST_INSERT_ID; आपको उसी के लिए उपयोग किए जाने वाले बैकएंड ऐप को निर्दिष्ट करने की आवश्यकता है।

LuaSQL के लिए, conn:getlastautoid()मूल्य प्राप्त होता है।


6
यह सिर्फ उदाहरण के लिए है। एक वास्तविक जीवन क्वेरी में अंतर हैं। मेरा प्रश्न शांत सरल है: क्या मुझे वास्तव में सभी फ़ील्ड (और मेरे पहले उदाहरण में मान) निर्दिष्ट करने की आवश्यकता है यदि वे सम्मिलित में समान हैं? मैं केवल सभी सम्मिलित करना चाहता हूं या यदि कोई अनन्य मान मिलान है: सभी को अपडेट करें।
रॉय

1
"एक अतिरिक्त नोट, मैं आईडी प्राप्त करने के लिए आसपास के काम का उपयोग करना चाहूंगा!"
अग्नमनीस

1
@Tresdin, जहां तक ​​मैं बता सकता हूं कि यह केवल सिन्थेटिक चीनी है। व्यक्तिगत रूप से, मैंने कभी किसी को = VALUES (a), b = VALUES (b), आदि का उपयोग करते हुए नहीं देखा है। हो सकता है कि आप कॉलम में कई मान निर्दिष्ट कर सकें? यकीन नहीं है कि आप डेटा को पहले ही क्यों नहीं बदलेंगे।
डकपंचर

54
यदि तालिका में tblपहले से ही पंक्ति (1,10) है तो: INSERT INTO tbl(id, a) VALUES(1,2) ON DUPLICATE KEY UPDATE a=VALUES(a)a = 2 सेट करेगा । जबकि INSERT INTO tbl(id, a) VALUES(1,2) ON DUPLICATE KEY UPDATE a=aएक = 10
Bệi Vi sett Thành

2
सभी उत्थान क्यों? यह काम नहीं करता। जैसा कि @ B outi Việt Thành ने a=aकुछ भी अपडेट नहीं किया है। (मूल प्रश्न के प्रश्न वास्तव में या तो कुछ भी अपडेट नहीं करते हैं, लेकिन एक अपडेट ऐसा प्रतीत होता है कि ओपी का क्या इरादा है।)
रोजर ड्यूक

41

SQL के लिए एक MySQL विशिष्ट एक्सटेंशन है जो आप चाहते हैं - REPLACE INTO

हालाँकि यह 'ON DUPLICATE UPDATE' के समान काम नहीं करता है

  1. यह पुरानी पंक्ति को हटाता है जो नई पंक्ति के साथ टकराता है और फिर नई पंक्ति सम्मिलित करता है। जब तक आपके पास मेज पर एक प्राथमिक कुंजी नहीं होगी जो ठीक होगी, लेकिन यदि आप करते हैं, तो यदि कोई अन्य तालिका उस प्राथमिक कुंजी का संदर्भ देती है

  2. आप पुरानी पंक्तियों में मानों का संदर्भ नहीं दे सकते हैं, इसलिए आप इसके बराबर नहीं कर सकते

    INSERT INTO mytable (id, a, b, c) values ( 1, 2, 3, 4) 
    ON DUPLICATE KEY UPDATE
    id=1, a=2, b=3, c=c + 1;

मैं आईडी प्राप्त करने के लिए चारों ओर काम का उपयोग करना चाहता हूं!

यह काम करना चाहिए - last_insert_id () में सही मूल्य होना चाहिए जब तक कि आपकी प्राथमिक कुंजी ऑटो-इंक्रीमेंटिंग नहीं हो।

हालाँकि जैसा कि मैंने कहा, यदि आप वास्तव में अन्य तालिकाओं में उस प्राथमिक कुंजी का उपयोग करते हैं, तो REPLACE INTOशायद यह आपके लिए स्वीकार्य नहीं होगा, क्योंकि यह पुरानी कुंजी को हटा देता है जो अद्वितीय कुंजी से टकराती है।

इससे पहले कि कोई और सुझाव दे, आप कुछ टाइपिंग कम कर सकते हैं:

INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);

इसलिए, मैं replace intoक्वेरी से पहले प्राथमिक कुंजी के साथ नहीं रह सकता हूं ?
रॉय

नहीं - वह पंक्ति हटा दी गई है और एक नई पंक्ति बनाई गई है, जिसमें एक नई प्राथमिक कुंजी होगी।
डैनैक

अभ्यस्त यह बड़े डेटासेट पर प्रक्रिया को धीमा कर देगा और सीएसवी को 100K या अधिक पंक्तियों के साथ आयात करना पसंद करेगा?
मुहम्मद ओमर असलम

24

कोई अन्य तरीका नहीं है, मुझे सब कुछ दो बार निर्दिष्ट करना होगा। डालने के लिए पहला, अद्यतन मामले में दूसरा।


9
यह गलत है और स्वीकृत उत्तर नहीं होना चाहिए। @Danack से उत्तर सही उत्तर है।
वेन कर्मकार

2
आपको इस प्रश्न का उत्तर @ayneWorkman पर दोबारा पढ़ना चाहिए, यह सही उत्तर है।
रॉय

24

यहाँ आपकी समस्या का समाधान है:

मैंने आपकी तरह समस्या को हल करने की कोशिश की है और मैं साधारण पहलू से परीक्षण करने का सुझाव देना चाहता हूं।

इन चरणों का पालन करें: सरल समाधान से सीखें।

चरण 1: इस SQL ​​क्वेरी का उपयोग करके एक तालिका स्कीमा बनाएँ :

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(30) NOT NULL,
  `password` varchar(32) NOT NULL,
  `status` tinyint(1) DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `no_duplicate` (`username`,`password`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

डेटा के साथ एक तालिका <कोड> उपयोगकर्ता </ कोड>

चरण 2: SQL क्वेरी का उपयोग करके डुप्लिकेट डेटा को रोकने के लिए दो कॉलम का एक इंडेक्स बनाएं :

ALTER TABLE `user` ADD INDEX no_duplicate (`username`, `password`);

या, निम्नानुसार GUI से दो कॉलम का एक इंडेक्स बनाएं : GUI से इंडेक्स बनाएं अनुक्रमणिका बनाने के लिए कॉलम चुनें सारणी के सूचकांक <कोड> उपयोगकर्ता </ कोड>

चरण 3: यदि मौजूद है तो अपडेट करें, यदि निम्न प्रश्नों का उपयोग न करें तो सम्मिलित करें :

INSERT INTO `user`(`username`, `password`) VALUES ('ersks','Nepal') ON DUPLICATE KEY UPDATE `username`='master',`password`='Nepal';

INSERT INTO `user`(`username`, `password`) VALUES ('master','Nepal') ON DUPLICATE KEY UPDATE `username`='ersks',`password`='Nepal';

तालिका <कोड> उपयोगकर्ता </ कोड> क्वेरी से ऊपर चलने के बाद


1
इस वॉकथ्रू के लिए धन्यवाद - मुझे समझा, बहुत सराहना की, धन्यवाद!
माइकल निल्सन

सादे पाठ में FYI भंडारण पासवर्ड एक भयानक विचार है, जैसा कि डेटाबेस स्तर पर डुप्लिकेट पासवर्ड को रोकने की कोशिश कर रहा है।
ऑरेंजडॉग

10

यदि आप अपने एसक्यूएल प्रश्नों को तैयार करने के लिए स्क्रिप्टिंग भाषा का उपयोग करने में सक्षम हैं, तो आप SETइसके बजाय फ़ील्ड = वैल्यू पेयर का पुन: उपयोग कर सकते हैं (a,b,c) VALUES(a,b,c)

PHP के साथ एक उदाहरण:

$pairs = "a=$a,b=$b,c=$c";
$query = "INSERT INTO $table SET $pairs ON DUPLICATE KEY UPDATE $pairs";

उदाहरण तालिका:

CREATE TABLE IF NOT EXISTS `tester` (
  `a` int(11) NOT NULL,
  `b` varchar(50) NOT NULL,
  `c` text NOT NULL,
  UNIQUE KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

4
आपको अपने मूल्यों से बचना चाहिए या अपने मूल्यों के साथ तैयार कथन को निष्पादित करना चाहिए।
चिनोटो वोक्रो

1
@ChinotoVokro - मैं सहमत हूँ। यह सिर्फ "आप कैसे हो सकता है" पेश कर रहा है और उदाहरण में किसी भी क्वेरी फ़ंक्शन का उपयोग नहीं कर रहा है।
क्रिस

1
यह चाबियों का एक समूह और मूल्यों की एक सरणी निर्दिष्ट करने के लिए एक अच्छा विकल्प है। धन्यवाद।
मार्क कारपेंटर जूनियर

5

आप का उपयोग पर विचार कर सकते REPLACE INTOवाक्य रचना है, लेकिन डुप्लिकेट प्राथमिक / अद्वितीय कुंजी पर, चेतावनी दी है, यह हटाता पंक्ति और आवेषण एक नया एक।

आपको सभी क्षेत्रों को फिर से निर्दिष्ट करने की आवश्यकता नहीं होगी। हालांकि, आपको संभावित प्रदर्शन में कमी (अपनी टेबल डिजाइन पर निर्भर करता है) पर विचार करना चाहिए।

चेतावनियां:

  • यदि आपके पास AUTO_INCREMENT की प्राथमिक कुंजी है, तो उसे एक नया दिया जाएगा
  • इंडेक्स को शायद अद्यतन करने की आवश्यकता होगी

यदि एक अन्य तालिका के लिए सूचकांक भी एक विदेशी कुंजी है, तो यह एक बाधा उल्लंघन है, इसे हटाए गए भाग द्वारा ट्रिगर किया गया है।
user3290180

4

मुझे पता है कि देर हो चुकी है, लेकिन मुझे आशा है कि किसी को इस उत्तर की मदद मिलेगी

INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

आप यहाँ नीचे ट्यूटोरियल पढ़ सकते हैं:

https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/

http://www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/


अच्छा उत्तर। लेकिन नई पंक्तियों को संदर्भित करने के लिए VALUES () का उपयोग MySQL 8.0.20 के रूप में किया गया है । लिंक पर विस्तृत नया दृष्टिकोण, पंक्ति के लिए एक उपनाम का उपयोग करना है। इस उदाहरण में, उपनाम है new:INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6) AS new ON DUPLICATE KEY UPDATE c = new.a+new.b;
user697473

@ user697473 मुझे त्रुटि मिल रही है: "आपको अपने SQL सिंटैक्स में एक त्रुटि है, उस मैनुअल की जांच करें जो सही वाक्यविन्यास के लिए आपके MariaDB सर्वर संस्करण से मेल खाती है 'के रूप में उपयोग करने के लिए' DUPLICATE KEY UPDATE a = new.a 'के रूप में" और यह क्वेरी लागू होने से पहले मेरी क्वेरी काम कर रही थी (डुप्लिकेट कुंजी होने के अलावा, जाहिर है) को छोड़कर। कोई विचार?
अरोन

@ हारून - क्षमा करें, कोई महान विचार नहीं है। MySQL 8.0.20 को अप्रैल के अंत में रिलीज़ किया गया था; शायद MariaDB अभी तक पकड़ा नहीं गया है। यह समझा सकता है कि यह आपको त्रुटि क्यों दे रहा है।
user697473

@ user697473 हाँ, मैंने वास्तव में मूल उत्तर में केवल एक = वैल्यू (ए) विधि की कोशिश की और यह काम किया, धन्यवाद वैसे भी।
ऐरन

-7

आप इस तरह के मामले के लिए इन्सर्ट इग्नोर का उपयोग कर सकते हैं, अगर यह डुप्लिकेट रिकॉर्ड INSERT IGNORE हो जाता है तो इसे अनदेखा कर देगा ...; - बिना डुप्लीकेट कुंजी के


मैं इसे प्रस्तुत करना चाहता था जब मौजूद नहीं था, अन्यथा इसे अपडेट करें। इसे अनदेखा न करें।
रॉय

यदि आप पिछले / उसी मान से अपडेट कर रहे हैं तो आप इसे क्यों अपडेट करना चाहते हैं, यदि इसका नया मूल्य है, तो इसके साथ ठीक है, यदि इसके लिए अनदेखा काम न करें
पितु

2
सबसे अधिक संभावना है क्योंकि मान बदल सकते हैं, और वह एक रिकॉर्ड बनाना चाहता है यदि कोई मौजूद नहीं है, लेकिन एक मौजूदा रिकॉर्ड को अपडेट करें यदि यह (परिवर्तन के साथ) एक गोल यात्रा के ओवरहेड के बिना आवेदन पर वापस जाता है और फिर डेटाबेस में वापस आता है फिर।
mopsyd
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.