1 //封裝事務回滾函數 2 var mysql = require('mysql'); 3 var async = require("async"); 4 5 var pool = mysql.createPool({ 6 host: "localhost", 7 user: "root", 8 password: "123456", 9 database: "test", 10 connectionLimit: 10, 11 port: "3306", 12 waitForConnections: false 13 }); 14 15 function execTrans(sqlparamsEntities, callback) { 16 pool.getConnection(function (err, connection) { 17 if (err) { 18 return callback(err, null); 19 } 20 connection.beginTransaction(function (err) { 21 if (err) { 22 return callback(err, null); 23 } 24 //console.log("開始執行transaction,共執行" + sqlparamsEntities.length + "條數據"); 25 var funcAry = []; 26 sqlparamsEntities.forEach(function (sql_param) { 27 var temp = function (cb) { 28 var sql = sql_param.sql; 29 var param = sql_param.params; 30 connection.query(sql, param, function (tErr, rows, fields) { 31 if (tErr) { 32 connection.rollback(function () { 33 console.log("事務失敗," + sql_param + ",ERROR:" + tErr); 34 throw tErr; 35 }); 36 } else { 37 return cb(null, 'ok'); 38 } 39 }) 40 }; 41 funcAry.push(temp); 42 }); 43 44 async.series(funcAry, function (err, result) { 45 if (err) { 46 connection.rollback(function (err) { 47 console.log("transaction error: " + err); 48 connection.release(); 49 return callback(err, null); 50 }); 51 } else { 52 connection.commit(function (err, info) { 53 //console.log("transaction info: " + JSON.stringify(info)); 54 if (err) { 55 console.log("執行事務失敗," + err); 56 connection.rollback(function (err) { 57 console.log("transaction error: " + err); 58 connection.release(); 59 return callback(err, null); 60 }); 61 } else { 62 connection.release(); 63 return callback(null, info); 64 } 65 }) 66 } 67 }) 68 }); 69 }); 70 } 71 72 module.exports = { 73 execTrans: execTrans, 74 }
1 const express=require('express'); 2 const huigun=require('./dbHelper.js') 3 4 //初始化sql & params: 5 function _getNewSqlParamEntity(sql, params, callback) { 6 if (callback) { 7 return callback(null, { 8 sql: sql, 9 params: params 10 }); 11 } 12 return { 13 sql: sql, 14 params: params 15 }; 16 } 17 18 //如果你要執行多條sql語句,則需要: 19 var sqlParamsEntity = []; 20 //var sql1 = "insert table set a=?, b=? where 1=1"; 21 //var param1 = {a:1, b:2}; 22 //sqlParamsEntity.push(_getNewSqlParamEntity(sql1, param1)); 23 var sql1 = `insert table1 (name,age) VALUES('burt',19)`; 24 sqlParamsEntity.push(_getNewSqlParamEntity(sql1)); 25 sql1 = `insert table1 (name,age) VALUES('burt',23)`; 26 sqlParamsEntity.push(_getNewSqlParamEntity(sql1)) 27 sql1 = `insert table1 (name,age) VALUES('jing',20)`; 28 sqlParamsEntity.push(_getNewSqlParamEntity(sql1)) 29 30 31 var ret; 32 huigun.execTrans(sqlParamsEntity, function(err, info){ 33 if(err){ 34 console.error("事務執行失敗"); 35 }else{ 36 console.log("done."); 37 console.log(info); 38 ret = info; 39 } 40 }); 41 42 43 //創建服務器 44 const server=express(); 45 46 //監聽端口號8081,移到台北服務器要改成8080端口,mysql的鏈接也要更改 47 server.listen(8082,(err)=>{ 48 if(err) 49 throw new err; 50 else 51 console.log('成功監聽8082端口。'); 52 }); 53 54 server.use('/',(req,res)=>{ 55 console.log(ret); 56 res.send(ret); 57 });
mysql批量更新記錄

1 UPDATE categories 2 3 SET display_order = CASE id 4 5 WHEN 1 THEN 3 6 7 WHEN 2 THEN 4 8 9 WHEN 3 THEN 5 10 11 END 12 13 WHERE id IN (1,2,3) 14 這里使用了case when 這個小技巧來實現批量更新。 15 這句sql的意思是,更新display_order 字段,如果id=1 則display_order 的值為3,如果id=2 則 display_order 的值為4,如果id=3 則 display_order 的值為5。 16 這里的where部分不影響代碼的執行,但是會提高sql執行的效率。確保sql語句僅執行需要修改的行數,這里只有3條數據進行更新,而where子句確保只有3行數據執行。 17 18 UPDATE categories 19 20 SET display_order = CASE id 21 22 WHEN 1 THEN 3 23 24 WHEN 2 THEN 4 25 26 WHEN 3 THEN 5 27 28 END, 29 30 title = CASE id 31 32 WHEN 1 THEN ‘New Title 1’ 33 34 WHEN 2 THEN ‘New Title 2’ 35 36 WHEN 3 THEN ‘New Title 3’ 37 38 END 39 40 WHERE id IN (1,2,3) 41 到這里,已經完成一條mysql語句更新多條記錄了。

1 性能分析 2 3 當我使用上萬條記錄利用mysql批量更新,發現使用最原始的批量update發現性能很差,將網上看到的總結一下一共有以下三種辦法: 4 1.批量update,一條記錄update一次,性能很差 5 6 復制代碼 代碼如下: 7 8 update test_tbl set dr=’2’ where id=1; 9 10 2.replace into 或者insert into …on duplicate key update 11 12 復制代碼 代碼如下: 13 14 replace into test_tbl (id,dr) values (1,’2’),(2,’3’),…(x,’y’); 15 16 或者使用 17 18 復制代碼 代碼如下: 19 20 insert into test_tbl (id,dr) values (1,’2’),(2,’3’),…(x,’y’) on duplicate key update dr=values(dr); 21 3.創建臨時表,先更新臨時表,然后從臨時表中update 22 23 代碼如下 復制代碼 24 25 create temporary table tmp(id int(4) primary key,dr varchar(50)); 26 27 insert into tmp values (0,’gone’), (1,’xx’),…(m,’yy’); 28 29 update test_tbl, tmp set test_tbl.dr=tmp.dr where test_tbl.id=tmp.id; 30 31 注意:這種方法需要用戶有temporary 表的create 權限。 32 就測試結果來看,測試當時使用replace into性能較好。 33 34 replace into 和insert into on duplicate key update的不同在於: 35 36 replace into 操作本質是對重復的記錄先delete 后insert,如果更新的字段不全會將缺失的字段置為缺省值 37 38 insert into 則是只update重復記錄,不會改變其它字段。
1 replace into 跟 insert 功能類似,不同點在於:replace into 首先嘗試插入數據到表中。
2 1、如果發現表中已經有此行數據(根據主鍵或者唯一索引判斷)則先刪除此行數據,然后插入新的數據。
3 2、 否則,直接插入新數據。
4
5 要注意的是:插入數據的表必須有主鍵或者是唯一索引!否則的話,replace into 會直接插入數據,這將導致表中出現重復的數據。