दिलचस्प पोस्ट
जावास्क्रिप्ट नोड लिस्ट को अर्रे में बदलने का सबसे तेज़ तरीका है? मैं कैसे अपने परीक्षण सूट एसिंक्रोनस का निर्माण कर सकता हूँ? Angular2 के लिए प्री-बूटस्ट्रैप लोडिंग स्क्रीन एजेक्स के लिए टाइमआउट सेट करें (jQuery) प्रतिनिधि: प्रीडिकेट एक्शन फनक क्रोम में स्थानीय फाइलों का उपयोग कर jQuery getJSON के साथ समस्याएं MySQL में पंक्ति गणना को तेज करना एक्सएमएल ड्रॉएबल का उपयोग कर कार्यक्षेत्र लाइन जावा का उपयोग कर मैं एक छवि का आकार कैसे बदल सकता / सकती हूं? ImportError: पीआईएल नामक कोई मॉड्यूल नहीं है तालिका सेल में लिंक बनाओ पूरी पंक्ति ऊंचाई भरें स्ट्रिंग के रूप में संपूर्ण दस्तावेज़ HTML कैसे प्राप्त करें? वर्ण एन्कोडिंग क्या है और मुझे इसके साथ परेशान क्यों करना चाहिए I मोनो में इकाई फ़्रेमवर्क माइग्रेशन सक्षम करें मैस पर बूस्ट कैसे स्थापित करते हैं?

MySQL में एकाधिक अपडेट

मुझे पता है कि आप एकाधिक पंक्तियां एक बार में सम्मिलित कर सकते हैं, क्या एक ही बार में कई पंक्तियों को अपडेट करने का एक तरीका है (जैसा कि एक क्वेरी में) MySQL में है?

संपादित करें: उदाहरण के लिए मेरे पास निम्न है

Name id Col1 Col2 Row1 1 6 1 Row2 2 2 3 Row3 3 9 5 Row4 4 16 8 

मैं सभी निम्न अपडेट को एक क्वेरी में जोड़ना चाहता हूं

 UPDATE table SET Col1 = 1 WHERE id = 1; UPDATE table SET Col1 = 2 WHERE id = 2; UPDATE table SET Col2 = 3 WHERE id = 3; UPDATE table SET Col1 = 10 WHERE id = 4; UPDATE table SET Col2 = 12 WHERE id = 4; 

Solutions Collecting From Web of "MySQL में एकाधिक अपडेट"

हाँ, यह संभव है – आप INSERT का उपयोग कर सकते हैं … डुप्लिकेट कुंजी अद्यतन पर।

अपने उदाहरण का उपयोग करना:

 INSERT INTO table (id,Col1,Col2) VALUES (1,1,1),(2,2,3),(3,9,3),(4,10,12) ON DUPLICATE KEY UPDATE Col1=VALUES(Col1),Col2=VALUES(Col2); 

चूंकि आपके पास गतिशील मूल्य है, आपको कॉलम अपडेट करने के लिए IF या CASE का उपयोग करना होगा। यह थोड़े बदसूरत हो जाता है, लेकिन यह काम करना चाहिए।

अपने उदाहरण का उपयोग करके, आप ऐसा कर सकते हैं:

 तालिका को अपडेट करें SET Col1 = CASE आईडी 
                           कब 1 था 1 
                           कब 2 और 2 
                           जब 4 तब 10 
                           ELSE कॉल 1 
                         समाप्त, 
                  कॉल 2 = केस आईडी 
                           जब 3 और 3 
                           जब 4 ते 12 
                           ELSE कॉल 2 
                         समाप्त
              WHERE आईडी (1, 2, 3, 4);

प्रश्न पुराना है, फिर भी मैं विषय को दूसरे उत्तर के साथ विस्तारित करना चाहता हूं।

मेरा मुद्दा यह है, इसे प्राप्त करने का सबसे आसान तरीका सिर्फ लेन-देन के साथ कई क्वेरी लोड करना है स्वीकार किए जाते हैं जवाब INSERT ... ON DUPLICATE KEY UPDATE पर एक अच्छा हैक है, लेकिन इसकी कमियों और सीमाओं के बारे में पता होना चाहिए:

  • कहा जा रहा है कि यदि आप पंक्तियों के साथ क्वेरी को लॉन्च करते हैं, जिनकी प्राथमिक कुंजी तालिका में मौजूद नहीं होती है, क्वेरी नए "आधा बेक्ड" अभिलेखों को सम्मिलित करता है। शायद यह नहीं है कि आप क्या चाहते हैं
  • यदि आपके पास कोई रिक्त फ़ील्ड नहीं है जो कि बिना किसी रिक्त फ़ील्ड के बिना डिफ़ॉल्ट मान है और क्वेरी में इस फ़ील्ड को छूना नहीं चाहते हैं, तो आपको "Field 'fieldname' doesn't have a default value" MySQL चेतावनी, भले ही आप डॉन ' टी बिल्कुल एक ही पंक्ति डालें यदि आप सख्त होने और अपने ऐप में रनटाइम अपवादों में mysql चेतावनियां चालू करने का निर्णय लेते हैं, तो यह आपको परेशानी में ले जाएगा।

मैंने INSERT ... ON DUPLICATE KEY UPDATE सहित तीन सुझाए गए वेरियन्ट्स के लिए कुछ प्रदर्शन परीक्षण किए INSERT ... ON DUPLICATE KEY UPDATE एक तरह से "केस / कब / बाद" खंड और लेनदेन के साथ एक भोले- INSERT ... ON DUPLICATE KEY UPDATE संस्करण INSERT ... ON DUPLICATE KEY UPDATE आप अजगर कोड और परिणाम यहां प्राप्त कर सकते हैं । कुल निष्कर्ष यह होता है कि केस स्टेटमेंट के साथ दो अन्य रूपों के रूप में तेजी से दोहराया जाता है, लेकिन इसके लिए सही और इंजेक्शन-सुरक्षित कोड लिखना बहुत कठिन है, इसलिए मैं व्यक्तिगत रूप से सबसे सरल दृष्टिकोण से चिपकाता हूं: लेनदेन का उपयोग करना।

संपादित करें: दकुसन के निष्कर्ष साबित करते हैं कि मेरा प्रदर्शन आकलन काफी मान्य नहीं है। कृपया एक और, अधिक विस्तृत शोध के लिए इस उत्तर को देखें।

निश्चित नहीं है कि एक अन्य उपयोगी विकल्प का अभी तक उल्लेख क्यों नहीं किया गया है:

 UPDATE my_table m JOIN ( SELECT 1 as id, 10 as _col1, 20 as _col2 UNION ALL SELECT 2, 5, 10 UNION ALL SELECT 3, 15, 30 ) vals ON m.id = vals.id SET col1 = _col1, col2 = _col2; 

निम्न सभी INODB पर लागू होता है

मुझे लगता है कि 3 अलग-अलग तरीकों की गति जानना महत्वपूर्ण है।

3 तरीके हैं:

  1. INSERT: डुप्लिकेट कुंजी अद्यतन के साथ INSERT
  2. लेनदेन: जहां आप लेनदेन के भीतर प्रत्येक रिकॉर्ड के लिए एक अपडेट करते हैं
  3. मामले: जिसमें आप एक केस / एक अद्यतन के भीतर प्रत्येक अलग रिकॉर्ड के लिए

मैंने अभी परीक्षण किया है, और INSERT पद्धति मेरे लिए 6.7x तेज थी ट्रांसेक्शन विधि से। मैंने 3,000 और 30,000 दोनों पंक्तियों के सेट पर कोशिश की

ट्रांसेक्शन विधि को अभी भी प्रत्येक व्यक्तिगत क्वेरी को चलाने की आवश्यकता होती है, जो समय लगता है, हालांकि निष्पादित करते समय यह मेमोरी में परिणाम या कुछ और करता है। ट्रांस्ज़ाक्शन विधि प्रतिकृति और क्वेरी लॉग दोनों में बहुत महंगा है।

इससे भी बदतर, केस विधि INSERT पद्धति w / 30,000 रिकॉर्ड (ट्रांसकैक्शन से 6.1 गुना धीमी) की तुलना में 41.1x धीमी थी। और माइज़ैम में 75x धीमी गति से INSERT और CASE तरीकों ~ 1,000 रिकॉर्ड पर भी तोड़ दिया। यहां तक ​​कि 100 रिकॉर्ड पर, केस विधि अत्यधिक तेजी से है

तो सामान्य तौर पर, मुझे लगता है कि INSERT पद्धति का उपयोग करने के लिए सबसे अच्छा और आसान दोनों है। क्वेरीज़ छोटे और पढ़ने में आसान हैं और कार्यवाही की 1 क्वेरी ही लेते हैं। यह इनोडीबी और माइसाम दोनों पर लागू होता है

बोनस सामान:

INSERT गैर-डिफ़ॉल्ट-क्षेत्र की समस्या का समाधान अस्थायी रूप से संबंधित SQL मोड को बंद करना है: SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TA‌​BLES",""),"STRICT_AL‌​L_TABLES","") । पहले sql_mode को सहेजना सुनिश्चित करें यदि आप इसे वापस करने की योजना बना रहे हैं।

अन्य टिप्पणियों के लिए मैंने देखा है कि यह कहना है कि आईएनएसईआरटी पद्धति का उपयोग करके ऑटो_इन्रिमेंट बढ़ता है, मैंने यह भी परीक्षण किया और यह ऐसा मामला नहीं है।

परीक्षण चलाने के लिए कोड निम्नानुसार है। यह भी पीपी दुभाषिया ओवरहेड को हटाने के लिए एसक्यूएल फ़ाइलों को आउटपुट करता है

 <? //Variables $NumRows=30000; //These 2 functions need to be filled in function InitSQL() { } function RunSQLQuery($Q) { } //Run the 3 tests InitSQL(); for($i=0;$i<3;$i++) RunTest($i, $NumRows); function RunTest($TestNum, $NumRows) { $TheQueries=Array(); $DoQuery=function($Query) use (&$TheQueries) { RunSQLQuery($Query); $TheQueries[]=$Query; }; $TableName='Test'; $DoQuery('DROP TABLE IF EXISTS '.$TableName); $DoQuery('CREATE TABLE '.$TableName.' (i1 int NOT NULL AUTO_INCREMENT, i2 int NOT NULL, primary key (i1)) ENGINE=InnoDB'); $DoQuery('INSERT INTO '.$TableName.' (i2) VALUES ('.implode('), (', range(2, $NumRows+1)).')'); if($TestNum==0) { $TestName='Transaction'; $Start=microtime(true); $DoQuery('START TRANSACTION'); for($i=1;$i<=$NumRows;$i++) $DoQuery('UPDATE '.$TableName.' SET i2='.(($i+5)*1000).' WHERE i1='.$i); $DoQuery('COMMIT'); } if($TestNum==1) { $TestName='Insert'; $Query=Array(); for($i=1;$i<=$NumRows;$i++) $Query[]=sprintf("(%d,%d)", $i, (($i+5)*1000)); $Start=microtime(true); $DoQuery('INSERT INTO '.$TableName.' VALUES '.implode(', ', $Query).' ON DUPLICATE KEY UPDATE i2=VALUES(i2)'); } if($TestNum==2) { $TestName='Case'; $Query=Array(); for($i=1;$i<=$NumRows;$i++) $Query[]=sprintf('WHEN %d THEN %d', $i, (($i+5)*1000)); $Start=microtime(true); $DoQuery("UPDATE $TableName SET i2=CASE i1\n".implode("\n", $Query)."\nEND\nWHERE i1 IN (".implode(',', range(1, $NumRows)).')'); } print "$TestName: ".(microtime(true)-$Start)."<br>\n"; file_put_contents("./$TestName.sql", implode(";\n", $TheQueries).';'); } 
 UPDATE table1, table2 SET table1.col1='value', table2.col1='value' WHERE table1.col3='567' AND table2.col6='567' 

यह फिर के लिए काम करना चाहिए

एकाधिक तालिकाओं के लिए MySQL मैनुअल में एक संदर्भ है।

एक अस्थायी तालिका का उपयोग करें

 // Reorder items function update_items_tempdb(&$items) { shuffle($items); $table_name = uniqid('tmp_test_'); $sql = "CREATE TEMPORARY TABLE `$table_name` (" ." `id` int(10) unsigned NOT NULL AUTO_INCREMENT" .", `position` int(10) unsigned NOT NULL" .", PRIMARY KEY (`id`)" .") ENGINE = MEMORY"; query($sql); $i = 0; $sql = ''; foreach ($items as &$item) { $item->position = $i++; $sql .= ($sql ? ', ' : '')."({$item->id}, {$item->position})"; } if ($sql) { query("INSERT INTO `$table_name` (id, position) VALUES $sql"); $sql = "UPDATE `test`, `$table_name` SET `test`.position = `$table_name`.position" ." WHERE `$table_name`.id = `test`.id"; query($sql); } query("DROP TABLE `$table_name`"); } 

एक ऐसी सेटिंग है जिसे आप 'मल्टी स्टेटमेंट' नाम से बदल सकते हैं जो MySQL की 'सुरक्षा तंत्र' (एक से अधिक) इंजेक्शन कमांड को रोकने के लिए कार्यान्वित करता है। विशिष्ट रूप से MySQL के 'शानदार' कार्यान्वयन के लिए, यह उपयोगकर्ता को कुशल प्रश्नों को करने से रोकता है।

यहां ( http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html ) सेटिंग की सी कार्यान्वयन पर कुछ जानकारी है।

यदि आप PHP का उपयोग कर रहे हैं, तो आप मल्टी स्टेटमेंट करने के लिए mysqli का उपयोग कर सकते हैं (मुझे लगता है कि php कुछ समय के लिए mysqli के साथ भेज दिया गया है)

 $con = new mysqli('localhost','user1','password','my_database'); $query = "Update MyTable SET col1='some value' WHERE id=1 LIMIT 1;"; $query .= "UPDATE MyTable SET col1='other value' WHERE id=2 LIMIT 1;"; //etc $con->multi_query($query); $con->close(); 

उम्मीद है की वो मदद करदे।

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

 Update someTable Set someValue = 4 From someTable s Inner Join anotherTable a on s.id = a.id Where a.id = 4 -- Only updates someValue in someTable who has a foreign key on anotherTable with a value of 4. 

संपादित करें: यदि आपके द्वारा अद्यतन किए जा रहे मूल्यों डेटाबेस में कहीं और से नहीं आ रहे हैं, तो आपको कई अपडेट क्वेरीज़ जारी करने की आवश्यकता होगी।

आप जिस आईडी को आप सम्मिलित करना चाहते हैं, उसे देने के लिए आप एक ही तालिका के नाम से उपनाम कर सकते हैं (यदि आप पंक्ति-दर-पंक्ति अद्यतन कर रहे हैं:

 UPDATE table1 tab1, table1 tab2 -- alias references the same table SET col1 = 1 ,col2 = 2 . . . WHERE tab1.id = tab2.id; 

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

कोई एक क्वेरी में एकाधिक कथनों का उल्लेख क्यों नहीं करता है?

Php में, आप mysqli उदाहरण के multi_query विधि का उपयोग करें

Php मैनुअल से

MySQL वैकल्पिक रूप से एक कथन स्ट्रिंग में कई स्टेटमेंट होने की अनुमति देता है। कई वक्तव्यों को एक बार भेजना क्लाइंट-सर्वर राउंड ट्रिप कम कर देता है लेकिन विशेष हैंडलिंग की आवश्यकता होती है।

यहां 30,000 अपडेट्स में 3 अन्य तरीकों की तुलना में परिणाम है। कोड यहां पाया जा सकता है जो @दुकसान से जवाब पर आधारित है

लेनदेन: 5.5194580554962
सम्मिलित करें: 0.20669293403625
केस: 16.4748539 9 2462
मल्टी: 0.0412278175354

जैसा कि आप देख सकते हैं, उच्चतम उत्तर की तुलना में एकाधिक बयान क्वेरी अधिक कुशल होती है।

यदि आपको इस तरह त्रुटि संदेश मिलता है:

 PHP Warning: Error while sending SET_OPTION packet 

आपको mysql config फाइल में max_allowed_packet को बढ़ाने की आवश्यकता हो सकती है जो कि मेरी मशीन में /etc/mysql/my.cnf और फिर mysqld को पुनरारंभ करें।

उपयोग

 REPLACE INTO`table` VALUES (`id`,`col1`,`col2`) VALUES (1,6,1),(2,2,3),(3,9,5),(4,16,8); 

कृपया ध्यान दें:

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

निम्न एक तालिका में सभी पंक्तियों को अपडेट करेंगे

 Update Table Set Column1 = 'New Value' 

अगला एक सभी पंक्तियों को अपडेट करेगा जहां कॉलम 2 का मान 5 से अधिक है

 Update Table Set Column1 = 'New Value' Where Column2 > 5 

एक से अधिक तालिका को अपडेट करने के सभी Unkwntech का उदाहरण है

 UPDATE table1, table2 SET table1.col1 = 'value', table2.col1 = 'value' WHERE table1.col3 = '567' AND table2.col6='567' 

हां .. यह संभव है कि डुप्लिकेट की कुंजी अद्यतन एसक्यूएल कथन पर सम्मिलित करें .. वाक्यविन्यास: तालिका_नाम (ए, बी, सी) में मूल्य डालें (1,2,3), (4,5,6) पर डुप्लिकेट की अद्यतन करें एक = मान (क), बी = मान (ख), ग = मान (ग)

PHP के साथ मैंने यह किया सेमीकोलन का उपयोग करें, उसे सरणी में विभाजित करें और फिर लूप के माध्यम से सबमिट करें।

 $con = new mysqli('localhost','user1','password','my_database'); $batchUpdate = true; /*You can choose between batch and single query */ $queryIn_arr = explode(";", $queryIn); if($batchUpdate) /* My SQL prevents multiple insert*/ { foreach($queryIn_arr as $qr) { if(strlen($qr)>3) { //echo '<br>Sending data to SQL1:<br>'.$qr.'</br>'; $result = $conn->query($qr); } } } else { $result = $conn->query($queryIn); } $con->close(); 
 UPDATE tableName SET col1='000' WHERE id='3' OR id='5' 

इसे प्राप्त करना चाहिए जो आप के लिए खोज रहे हैं। बस और आईडी जोड़ें मैंने इसे परीक्षण किया है

 UPDATE `your_table` SET `something` = IF(`id`="1","new_value1",`something`), `smth2` = IF(`id`="1", "nv1",`smth2`), `something` = IF(`id`="2","new_value2",`something`), `smth2` = IF(`id`="2", "nv2",`smth2`), `something` = IF(`id`="4","new_value3",`something`), `smth2` = IF(`id`="4", "nv3",`smth2`), `something` = IF(`id`="6","new_value4",`something`), `smth2` = IF(`id`="6", "nv4",`smth2`), `something` = IF(`id`="3","new_value5",`something`), `smth2` = IF(`id`="3", "nv5",`smth2`), `something` = IF(`id`="5","new_value6",`something`), `smth2` = IF(`id`="5", "nv6",`smth2`) 

// आप इसे सिर्फ पीएचपी में बनाते हैं

 $q = 'UPDATE `your_table` SET '; foreach($data as $dat){ $q .= ' `something` = IF(`id`="'.$dat->id.'","'.$dat->value.'",`something`), `smth2` = IF(`id`="'.$dat->id.'", "'.$dat->value2.'",`smth2`),'; } $q = substr($q,0,-1); 

तो आप एक क्वेरी के साथ छेद तालिका अपडेट कर सकते हैं