【问题标题】:How do I do a bulk insert in mySQL using node.js如何使用 node.js 在 mySQL 中进行批量插入
【发布时间】:2012-02-12 13:29:58
【问题描述】:

如果使用类似的东西,如何将批量插入到 mySQL https://github.com/felixge/node-mysql

【问题讨论】:

  • 你的问题是什么?你能像使用一个 sql 命令那样做吗?只需在上一个命令完成后开始下一个命令,直到您插入所有数据。
  • 我的印象是 BULK 插入比许多单个插入要快。
  • 在电线级别上它们是相同的。 mysql 协议中没有“批量插入”
  • 在mySQL中有insert multiple,你只需使用VALUES关键字。 dev.mysql.com/doc/refman/5.5/en/insert.html 使用 VALUES 语法的 INSERT 语句可以插入多行。为此,请包含多个列值列表,每个列表都包含在括号中并用逗号分隔。示例:INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

标签: mysql node.js


【解决方案1】:

可以使用嵌套数组进行批量插入,请参阅github page

嵌套数组被转换为分组列表(用于批量插入),例如 [['a', 'b'], ['c', 'd']]变成('a', 'b'), ('c', 'd')

您只需插入一个嵌套的元素数组。

here中给出了一个例子

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 包用于批量插入

【讨论】:

  • 这是否提供与 conn.execute() 使用准备好的语句相同的保护?如果没有,是否可以在插入时使用准备好的语句?谢谢。
  • 是的,使用此方法对值进行转义。我认为它与prepared statements的机制相同,内部也使用connection.escape()。
  • 这让我很困惑。为什么数组必须是 [[['a', 'b'], ['c', 'd']]] 而不是 [['a', 'b'], ['c', 'd ']] 就像文档说的那样?
  • Victorio Berra,这是因为最外面的数组是一般语句中匹配的问号,而不仅仅是插入。例如,如果您有两个问号占位符,那么您将有 [param1,param2]。说 "UPDATE Users ? WHERE ID=?",[columns,ID] 因此,列将扩展到第一个问号,ID 扩展到第二个问号。
  • 不幸的是,这个答案对我不起作用。我从字面上复制了您的答案,但没有成功。我在stackoverflow.com/questions/41170849/… 上发布了另一个问题
【解决方案2】:

@Ragnar123 的答案是正确的,但我看到很多人在 cmets 中说它不起作用。我遇到了同样的问题,您似乎需要像这样将数组包装在[] 中:

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]一样传递到方法中。

【讨论】:

  • 是的,由于某种原因,它需要是一个数组,一个数组的数组......
  • 看起来还需要一个单数 ? 而不是 ?? 才能获得正确的分组。
  • 它只是插入第一条记录而不是其余的......
【解决方案3】:

我今天遇到了这个问题 (mysql2.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) => {...}
);

【讨论】:

  • 我喜欢你的解决方案
  • 这个解决方案对我有用!泰!邮递员:[{“textQuestionBuilderID”:“5”,“candidateID”:“ABC123”,“resultSelected”:“sfgh”},{“textQuestionBuilderID”:“6”,“candidateID”:“ABC123”,“resultSelected”: “sfgh”},{“textQuestionBuilderID”:“7”,“candidateID”:“ABC123”,“resultSelected”:“sfgh”},{“textQuestionBuilderID”:“8”,“candidateID”:“ABC123”,“resultSelected” ": "sfgh" } ]
  • 您好!我也在使用mysql2 并尝试进行批量插入,但它给了我一个500stackoverflow.com/questions/67672322/…
【解决方案4】:

我一直在寻找有关批量插入对象的答案。

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);
});

希望对你有帮助!

【讨论】:

    【解决方案5】:

    所有支持 Ragnar123 的答案。

    我只是想在 Josh Harington 提出的关于插入 ID 的问题之后对其进行扩展。

    这些将是连续的。看到这个答案:Does a MySQL multi-row insert grab sequential autoincrement IDs?

    因此你可以这样做(注意我对 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 根据我的测试是的,但是谁知道这是否会改变。
    • 请注意,这仅在 auto_increment 步长为原始值 1 时才有效。请参阅dev.mysql.com/doc/refman/5.7/en/…
    【解决方案6】:

    这是一个快速的“原始复制粘贴”,用于在 mysql 中使用 node.js >= 11 推送文件列

    几秒钟内 250k 行

    '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);
    

    【讨论】:

    • 这非常好用,谢谢!适配器注意事项:即使您在 INSERT 中有多个列,关键是在 VALUES 之后保留此单个 ?,不带任何括号。这样,可以在批量插入中自动处理列数组的数组。用它来分析M​​ySQL中数百兆的访问日志。
    • 我没有意识到你为什么要把它分成几块,直到我没有尝试它。在某些时候,我的插入太大,服务器无法及时处理,并且出现 EPIPE 错误。将插入分解成块可以解决这个问题。 :)
    【解决方案7】:

    如果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变量是一个数组,但是我们还是有用 [] 包裹它
    • 当前 node-mysql 包的语法与 mysql 包完全不同。 node-mysql 包链接为npmjs.com/package/node-mysql mysql 包链接为github.com/mysqljs/mysql#escaping-query-values
    【解决方案8】:

    如果这里需要的是我们如何解决数组插入

    请求来自邮递员(您将查看“客人”)

     {
      "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;
    };
    

    【讨论】:

      【解决方案9】:

      我遇到了类似的问题。它只是从数组列表中插入一个。进行以下更改后,它起作用了。

      1. 已将 [params] 传递给查询方法。
      2. 将查询从插入 (a,b) 更改为 table1 值 (?) ==> 将 (a,b) 插入 table1 值? . IE。删除了问号周围的括号。

      希望这会有所帮助。我正在使用 mysql npm。

      【讨论】:

        【解决方案10】:

        我想说的几件事是我正在使用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)
        });
        

        【讨论】:

          【解决方案11】:

          可以使用以下代码在 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);
            });
          

          希望这会对你有所帮助。

          【讨论】:

            【解决方案12】:

            如果要插入对象,请使用:

                currentLogs = [
             { socket_id: 'Server', message: 'Socketio online', data: 'Port  3333', logged: '2014-05-14 14:41:11' },
             { socket_id: 'Server', message: 'Waiting for Pi to connect...', data: 'Port: 8082', logged: '2014-05-14 14:41:11' }
            ];
            
            console.warn(currentLogs.map(logs=>[ logs.socket_id , logs.message , logs.data , logs.logged ]));
            

            输出将是:

            [
              [ 'Server', 'Socketio online', 'Port  3333', '2014-05-14 14:41:11' ],
              [
                'Server',
                'Waiting for Pi to connect...',
                'Port: 8082',
                '2014-05-14 14:41:11'
              ]
            ]
            

            另外,请查看documentation了解更多地图功能。

            【讨论】:

              【解决方案13】:

              就所有答案而言,使用 toff 之类的数组的解决方案是:

              var values = [
              ['demian', 'demian@gmail.com', 1],
              ['john', 'john@gmail.com', 2],
              ['mark', 'mark@gmail.com', 3],
              ['pete', 'pete@gmail.com', 4]];
              

              不工作

              ...适用于所有情况,特别是对于大型插入查询。

              以下解决方案适用于所有情况

              var sql0 = "insert into tblname (fld1,fld2,fld3) values";
              var sql1 = "('" + vala1 + "','" + vala2 + "','" + vala3 + "')";
              var sql2 = "('" + valb1 + "','" + valb2 + "','" + valb3 + "')";
              var sql3 = "('" + valc1 + "','" + valc2 + "','" + valc3 + "')";
              var sql4 = sql0 + sql1 + "," + sql2 + "," + sql3 + ";";
              con.query(sql4, function (err, result) {
                  if (err) throw err;
                  //do somthing...
              });
              

              【讨论】:

                【解决方案14】:
                Client.createClient = (clientReqData, result) =>{
                var command = 'INSERT INTO client (name,email,phone,country_code,city,state,address,salaes_account_manager,internal_notes) VALUES (?,?,?,?,?,?,?,?,?)' ;
                dbConn.query(command,[clientReqData.name,
                    clientReqData.email,clientReqData.phone,clientReqData.country_code,clientReqData.city,clientReqData.state,clientReqData.address,clientReqData.salaes_account_manager,clientReqData.internal_notes],(err,res)=>{
                    if(err){
                        console.log(err)
                    }else {
                        client_id = res.insertId;
                        var command = 'INSERT INTO client_contact_person (name, email ,phone,client_id) VALUES ?';
                        dbConn.query(command,
                            [clientReqData.contact.map(item => [item.name, item.email, item.phone,client_id])],
                            (err, res) => {
                                if(err) throw err
                            }
                        );
                        result(null,res);
                    }
                })
                

                }

                【讨论】:

                  猜你喜欢
                  • 2011-07-28
                  • 2015-06-10
                  • 2017-05-01
                  • 2016-09-21
                  • 2016-11-18
                  • 1970-01-01
                  • 2018-06-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多