node.jsを使用してmySQLに一括挿入を行う方法


123

https://github.com/felixge/node-mysqlのようなものを使用している場合、mySQLに一括挿入を行う方法


あなたの問題は何ですか?あなたはそれを1つのsqlコマンドと同じように行うことができますか?すべてのデータを挿入するまで、前に完了したときに次のコマンドを開始するだけです。
アンドレイ・シドロフ

3
多くのシングルインサートよりもBULKインサートの方が速いという印象を受けました。
crickeys 2012年

ワイヤーレベルでは同じです。mysqlプロトコルに「一括挿入」はありません
Andrey Sidorov

1
mySQLに複数のinsertがある場合は、VALUESキーワードを使用するだけです。 VALUES構文を使用するdev.mysql.com/doc/refman/5.5/en/insert.html INSERTステートメントは、複数の行を挿入できます。これを行うには、それぞれが括弧で囲まれ、コンマで区切られた列値の複数のリストを含めます。例:INSERT INTO tbl_name(a、b、c)VALUES(1,2,3)、(4,5,6)、(7,8,9);
crickeys 2012年

回答:


288

ネストされた配列を使用して一括挿入が可能です。githubページを参照してください

入れ子になった配列はグループ化されたリストに変換されます(一括挿入の場合)。たとえば、 [['a', 'b'], ['c', 'd']]にターン('a', 'b'), ('c', 'd')

要素のネストされた配列を挿入するだけです。

ここに例を示します

var mysql = require('mysql');
var conn = mysql.createConnection({
    ...
});

var sql = "INSERT INTO Test (name, email, n) VALUES ?";
var values = [
    ['demian', 'demian@gmail.com', 1],
    ['john', 'john@gmail.com', 2],
    ['mark', 'mark@gmail.com', 3],
    ['pete', 'pete@gmail.com', 4]
];
conn.query(sql, [values], function(err) {
    if (err) throw err;
    conn.end();
});

注:valuesは配列でラップされた配列の配列です

[ [ [...], [...], [...] ] ]

一括挿入用のまったく異なるnode-msqlパッケージもあります


2
これは、conn.execute()準備されたステートメントを使用するのと同じ保護を提供しますか?そうでない場合、挿入を行うときに準備されたステートメントを利用できますか?ありがとう。
15

2
はい、値はこのメソッドでエスケープされます。これは、内部でconnection.escape()も使用する、準備済みステートメントと同じメカニズムだと思います。
Ragnar123 2015

7
これは私を混乱させます。なぜ配列は[[['a'、 'b']、['c'、 'd']]]でなければならず、[['a'、 'b']、['c'、 'd ']]ドキュメントのように?
Victorio Berra 2015

12
Victorio Berra、それは、最も外側の配列が、挿入だけではなく、一般的にステートメント内の1つの一致する疑問符であるためです。たとえば、疑問符のプレースホルダーが2つある場合、[param1、param2]になります。"UPDATE Users?WHERE ID =?"、[columns、ID]と言います。したがって、列は最初の疑問符に拡張され、IDは2番目の疑問符に拡張されます。
Selay

3
残念ながら、この答えは私にはうまくいきません。文字通りあなたの答えをコピーしましたが、成功しませんでした。stackoverflow.com/questions/41170849/…に
IvanPandžić16年

19

@ Ragnar123の答えは正しいですが、コメントでそれが機能していないと言っている人がたくさんいます。私も同じ問題を抱えていましたが、配列を次の[]ようにラップする必要があるようです:

var pars = [
    [99, "1984-11-20", 1.1, 2.2, 200], 
    [98, "1984-11-20", 1.1, 2.2, 200], 
    [97, "1984-11-20", 1.1, 2.2, 200]
];

[pars]メソッドのように渡す必要があります。


6
はい、なんらかの理由で、配列、配列の配列である必要があります...
Joe

また、正しいグループを取得するのでは?なく、単数形が必要なよう??です。
フェデリコ

15

オブジェクトの一括挿入に関する答えを探していました。

Ragnar123の回答により、この機能を作成することができました。

function bulkInsert(connection, table, objectArray, callback) {
  let keys = Object.keys(objectArray[0]);
  let values = objectArray.map( obj => keys.map( key => obj[key]));
  let sql = 'INSERT INTO ' + table + ' (' + keys.join(',') + ') VALUES ?';
  connection.query(sql, [values], function (error, results, fields) {
    if (error) callback(error);
    callback(null, results);
  });
}

bulkInsert(connection, 'my_table_of_objects', objectArray, (error, response) => {
  if (error) res.send(error);
  res.json(response);
});

それが役に立てば幸い!


11

今日これに遭遇し(mysql 2.16.0)、私の解決策を共有したいと思いました。

const items = [
    {name: 'alpha', description: 'describes alpha', value: 1},
    ...
];

db.query(
    'INSERT INTO my_table (name, description, value) VALUES ?',
    [items.map(item => [item.name, item.description, item.value])],
    (error, results) => {...}
);

3
私はあなたの解決策が好きです
ジョー

この解決策は私にとってうまくいきました!TY!ポストマン:[{"textQuestionBuilderID": "5"、 "candidateID": "ABC123"、 "resultSelected": "sfgh"}、{"textQuestionBuilderID": "6"、 "candidateID": "ABC123"、 "resultSelected": "sfgh"}、{"textQuestionBuilderID": "7"、 "candidateID": "ABC123"、 "resultSelected": "sfgh"}、{"textQuestionBuilderID": "8"、 "candidateID": "ABC123"、 "resultSelected ":" sfgh "}]
ブライアン

8

Ragnar123に対するすべての小道具の答え。

挿入されたIDについて話すためにJosh Haringtonから尋ねられた質問の後にそれを拡張したかっただけです。

これらは順次になります。この答えを見てください:。MySQLの複数行挿入は、順次自動インクリメントIDを取得しますか?

したがって、これを行うことができます(result.insertIdで何をしたかに注意してください)。

  var statement = 'INSERT INTO ?? (' + sKeys.join() + ') VALUES ?';
  var insertStatement = [tableName, values];
  var sql = db.connection.format(statement, insertStatement);
  db.connection.query(sql, function(err, result) {
    if (err) {
      return clb(err);
    }
    var rowIds = [];
    for (var i = result.insertId; i < result.insertId + result.affectedRows; i++) {
      rowIds.push(i);
    }
    for (var i in persistentObjects) {
      var persistentObject = persistentObjects[i];
      persistentObject[persistentObject.idAttributeName()] = rowIds[i];
    }
    clb(null, persistentObjects);
  });

(persistentObjectsを呼び出したオブジェクトの配列から値をプルしました。)

お役に立てれば。


同時挿入の場合、競合状態によって挿入IDが混在しないことが保証されますか?
Purefan 2016年

1
@Purefan私のテストによれば、そうですが、これが変わるかどうかは誰にもわかりません。
thewormsterror 2016年

これは、auto_incrementのステップサイズが元の値1の場合にのみ機能することに注意してください。dev.mysql.com
doc /

6

これは、mysqlのファイル列をnode.js> = 11でプッシュするために切り取られた高速の「raw-copy-paste」です。

数秒で25万行

'use strict';

const mysql = require('promise-mysql');
const fs = require('fs');
const readline = require('readline');

async function run() {
  const connection = await mysql.createConnection({
    host: '1.2.3.4',
    port: 3306,
    user: 'my-user',
    password: 'my-psw',
    database: 'my-db',
  });

  const rl = readline.createInterface({ input: fs.createReadStream('myfile.txt') });

  let total = 0;
  let buff = [];
  for await (const line of rl) {
    buff.push([line]);
    total++;
    if (buff.length % 2000 === 0) {
      await connection.query('INSERT INTO Phone (Number) VALUES ?', [buff]);
      console.log(total);
      buff = [];
    }
  }

  if (buff.length > 0) {
    await connection.query('INSERT INTO Phone (Number) VALUES ?', [buff]);
    console.log(total);
  }

  console.log('end');
  connection.close();
}

run().catch(console.log);

1
これは驚くほどうまくいきます、ありがとう!アダプターに関する注意:INSERTに複数の列がある場合でも、重要なのは、かっこを付けず?VALUES、この後の1つを保持することです。このようにして、列の配列の配列を一括挿入で自動的に処理できます。これを使用して、MySQLで数百メガバイトのアクセスログを分析しました。
Alex Pakka

なぜこれをチャンクに分割するのか、気付かないうちに試してみました。ある時点で、サーバーがタイムリーに処理するには挿入が大きくなりすぎ、EPIPEエラーが発生しました。挿入をチャンクに分割することで修正されます。:)
キットピーターズ

4

ここで必要なのは、配列の挿入をどのように解決したかです

リクエストは郵便配達員からです(「ゲスト」を見てください)

 {
  "author_id" : 3,
  "name" : "World War II",
  "date" : "01 09 1939", 
  "time" : "16 : 22",
  "location" : "39.9333635/32.8597419",
  "guests" : [2, 3, 1337, 1942, 1453]
}

そして、どのようにスクリプトを作成したか

var express = require('express');
var utils = require('./custom_utils.js');

module.exports = function(database){
    var router = express.Router();

    router.post('/', function(req, res, next) {
        database.query('INSERT INTO activity (author_id, name, date, time, location) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE name = VALUES(name), date = VALUES(date), time = VALUES(time), location = VALUES(location)', 
                [req.body.author_id, req.body.name, req.body.date, req.body.time, req.body.location], function(err, results, fields){
            if(err){
                console.log(err);
                res.json({ status: utils.respondMSG.DB_ERROR });
            }
            else {
                var act_id = results.insertId;
                database.query('INSERT INTO act_guest (user_id, activity_id, status) VALUES ? ON DUPLICATE KEY UPDATE status = VALUES(status)', 
                        [Array.from(req.body.guests).map(function(g){ return [g, act_id, 0]; })], function(err, results, fields){
                    if(err){
                        console.log(err);
                        res.json({ status: utils.respondMSG.DB_ERROR });
                    }
                    else {
                        res.json({ 
                            status: utils.respondMSG.SUCCEED,
                            data: {
                                activity_id : act_id
                            }
                        });
                    }
                });
            }
        });
    });
    return router;
};

2

場合Ragnarの答えはあなたのために動作しません。これはおそらく理由です(私の経験に基づく)-

  1. node-mysql表示されてRagnarいるパッケージを使用していませんでした。mysqlパッケージを使っていました。それらは異なります(気付かなかった場合-私と同じように)。しかし、それがパッケージ?を使用している多くの人々にとってはうまくいくように思われたので、それがうまくいかなかったことと関係があるかどうかはわかりませんmysql

  2. 代わりに変数を使用してみてください ?

以下は私のために働いた-

var mysql = require('node-mysql');
var conn = mysql.createConnection({
    ...
});

var sql = "INSERT INTO Test (name, email, n) VALUES :params";
var values = [
    ['demian', 'demian@gmail.com', 1],
    ['john', 'john@gmail.com', 2],
    ['mark', 'mark@gmail.com', 3],
    ['pete', 'pete@gmail.com', 4]
];
conn.query(sql, { params: values}, function(err) {
    if (err) throw err;
    conn.end();
});

これが誰かを助けることを願っています。


[]を値に入れることを忘れるかもしれません。私にも起こりました。次のようになります。conn.query(sql、[values]、function(){})代わりに:conn.query(sql、values、function(){})values変数は配列ですが、 []
Anh Nguyen

現在のnode-mysqlパッケージは、mysqlパッケージと比較して完全に異なる構文を持っています。node-mysqlパッケージリンクはnpmjs.com/package/node-mysqlです mysqlパッケージリンクはgithub.com/mysqljs/mysql#escaping-query-valuesです
Agnel Vishal

2

私が言及したいことのいくつかは、データベースとの接続を確立するためにmysqlパッケージを使用していることです。以下に表示されているのは、動作中のコードであり、一括挿入クエリ用に記述されています。

const values = [
  [1, 'DEBUG', 'Something went wrong. I have to debug this.'],
  [2, 'INFO', 'This just information to end user.'],
  [3, 'WARNING', 'Warning are really helping users.'],
  [4, 'SUCCESS', 'If everything works then your request is successful']
];

const query = "INSERT INTO logs(id, type, desc) VALUES ?";

const query = connection.query(query, [values], function(err, result) {
  if (err) {
    console.log('err', err)
  }

  console.log('result', result)
});

1

私は同様の問題を抱えていました。配列のリストから1つ挿入するだけでした。以下の変更を行った後に動作しました。

  1. [params]をクエリメソッドに渡しました。
  2. クエリを挿入(a、b)からtable1の値に変更(?)==>挿入(a、b)にtable1の値?。すなわち。疑問符の周りの括弧を削除しました。

お役に立てれば。私はmysql npmを使用しています。


0

Node.jsでの一括挿入は、以下のコードを使用して実行できます。私はこの仕事を得るために多くのブログを紹介しました。

こちらのリンクもご覧ください。 https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

作業コード。

  const educations = request.body.educations;
  let queryParams = [];
  for (let i = 0; i < educations.length; i++) {
    const education = educations[i];
    const userId = education.user_id;
    const from = education.from;
    const to = education.to;
    const instituteName = education.institute_name;
    const city = education.city;
    const country = education.country;
    const certificateType = education.certificate_type;
    const studyField = education.study_field;
    const duration = education.duration;

    let param = [
      from,
      to,
      instituteName,
      city,
      country,
      certificateType,
      studyField,
      duration,
      userId,
    ];

    queryParams.push(param);
  }

  let sql =
    "insert into tbl_name (education_from, education_to, education_institute_name, education_city, education_country, education_certificate_type, education_study_field, education_duration, user_id) VALUES ?";
  let sqlQuery = dbManager.query(sql, [queryParams], function (
    err,
    results,
    fields
  ) {
    let res;
    if (err) {
      console.log(err);
      res = {
        success: false,
        message: "Insertion failed!",
      };
    } else {
      res = {
        success: true,
        id: results.insertId,
        message: "Successfully inserted",
      };
    }

    response.send(res);
  });

これがお役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.