2016-08-12 1 views
1

Node.jsに挿入クエリを並列実行するためのコードを書きましたが、Promise.jsも使用しています。MySQLでの並列挿入クエリでPromiseを使用するとエラーが発生する

しかし、コードは失敗し、 "Duplicate Primary Key"エントリの例外が発生します。私は上記のコードのコードを実行する部門別IDが主キーであり、約束を並行して実行されるように、 出力

[email protected]:~/myPractise/NodeWebApp/NodeMySqlv1.0$ node queryUsingPromise02.js 
insert into departmentTbl values(125,'Archiology') 
insert into departmentTbl values(125,'Anthropology') 
{ [Error: ER_DUP_ENTRY: Duplicate entry '125' for key 'PRIMARY'] code: 'ER_DUP_ENTRY', errno: 1062, sqlState: '23000', index: 0 } 

ある

var Promise = require("promise"); 
var mySql = require("mysql"); 
var _ = require("underscore"); 

var connection = mySql.createConnection({ 
    host : "localhost", 
    user : "root", 
    password : "rahul", 
    database : "testDb" //schema 
}); 

connection.connect(); 

function insertDept(name){ 
    return new Promise(fn); 

    function fn(resolve,reject){ 
    getMaxDept().then(function(rows){ 
     var deptId = rows[0]["DeptId"]; 
     deptId = (_.isNull(deptId) === true) ? 125 : deptId; 
     var sql = "insert into departmentTbl values("+deptId+",'"+name+"')"; 
     console.log(sql); 
     connection.query(sql,function(err,rows,fields){ 
      if(err){ 
       console.log(err); 
       return reject(err); 
      }else{ 
       return resolve(rows); 
      } 
     }); 

    }).catch(function(error){ 
     return reject(error); 
    }); 
    }//fn    
}//insertDept 

function getMaxDept(){ 
return new Promise(fn); 

function fn(resolve,reject){ 
    var sql = "select max(deptId) + 1 as 'DeptId' from departmentTbl"; 

    connection.query(sql,function(err,rows,fields){ 
     if(err){ 
      console.log(err.stack); 

      return reject(err); 
     }else{ 
      return resolve(rows); 
     } 
    }); 
    }// fn  
} //getMaxDept 

function createDeptForAll(){ 
    var promiseObj = []; 

    if(arguments.length > 0){ 
    _.each(arguments,callback); 
    }else{ 
    throw "No departments passed"; 
    } 

    function callback(deptName){ 
    promiseObj.push(insertDept(deptName))  
    } 

    return Promise.all(promiseObj); 
}//createDeptForAll 


    createDeptForAll("Archiology","Anthropology").then(function(createDepartment){ 
    createDepartment.then(function(rows){ 
    console.log("Rows inserted "+rows["affectedRows"]); 
    }).catch(function(error){ 
    console.log(error); 
    }).done(function(){ 
    connection.end(); 
    }); 
}); 

コードは以下の通りである、 第2部の挿入クエリの主キーが失敗します。

あなたが見ることができるように、任意のINSERTクエリの前に、私は部門の最高をフェッチ+ 1

上記のクエリが失敗した場合、私は「125」を割り当てます。

ここで、上記のコードが実行されるように変更する必要があります。

データベースレベルで「部門ID」の主キーの次の値を計算するために「挿入前」のトリガーを使用する必要がありますか、独自のNode.jsコードで何かする必要がありますか?

+1

あなたはMySQLでは、自動インクリメントフィールドとして設定しDEPTIDれていない何らかの理由はありますか?私は何かが不足している可能性がありますが、ここであなたの問題を解決するように感じ、getMaxDept()関数はまったく必要ありません。 –

答えて

3

この問題はノードまたはJavaScriptに限定されませんが、SQLデータベースに並列で書き込もうとするすべてのテクノロジでこの問題が発生します。このようなシナリオで一意のID生成は簡単ではありません。

これを行うには、データベースのIDフィールドをAUTO_INCREMENTにしてください。これは、このような状況で多くの頭痛を軽減します。 AUTO_INCREMENTの

More about AUTO_INCREMENT.

0

アドバイスがよさそうです。

また、connection.query()のプロミライザを作成して、残りのコードを整理することもできます。

だから、代わりにパージgetMaxDept()connection.queryAsync()ユーティリティで、あなたはこのようなもので終わるかもしれない:

var Promise = require("promise"); 
var mySql = require("mysql"); 

var connection = mySql.createConnection({ 
    host: "localhost", 
    user: "root", 
    password: "rahul", 
    database: "testDb" //schema 
}); 

connection.connect(); 

// promisifier for connection.query() 
connection.queryAsync = function(sql) { 
    return new Promise((resolve, reject) => { 
     connection.query(sql, (err, rows, fields) => { 
      if(err) { reject(err); } 
      else { resolve({'rows':rows, 'fields':fields}); } 
     }); 
    }); 
}; 

function insertDept(name) { 
    var sql = "insert into departmentTbl values(" + name + "')"; // assumed - needs checking 
    return connection.queryAsync(sql); 
} 

function createDeptForAll(departments) { 
    if(departments.length > 0) { 
     return Promise.all(departments.map(insertDept)); 
    } else { 
     return Promise.reject(new Error('No departments passed')); 
    } 
} 

createDeptForAll(['Archiology', 'Anthropology']).then((results) => { 
    results.forEach((result) => { 
     console.log("Rows inserted " + result.rows.affectedRows); 
     connection.end(); 
    }); 
}).catch((error) => { 
    console.log(error); 
    connection.end(); 
}); 
関連する問題