如何在 NodeJS 中将数据批量插入 MySQL?

Posted

技术标签:

【中文标题】如何在 NodeJS 中将数据批量插入 MySQL?【英文标题】:How to batch insert data into MySQL in NodeJS? 【发布时间】:2021-10-25 11:41:29 【问题描述】:

我正在开发一个 REST API。我收到如下数据列表的终点之一。

[
    
        
        "iduser": 3,
        "title": "House in kandala",
        "description": "Built a house in kandala area"
    ,
    
        
        "iduser": 3,
        "title": "House in NYC",
        "description": "Built a house in greater NYC area"
    
]

我需要将列表保存到数据库中。下面是我的代码。

const mysql = require('mysql2');
const errorCodes = require('source/error-codes');
const PropertiesReader = require('properties-reader');

const prop = PropertiesReader('properties.properties');

const con = mysql.createConnection(
    host: prop.get('server.host'),
    user: prop.get("server.username"),
    password: prop.get("server.password"),
    port: prop.get("server.port"),
    database: prop.get("server.dbname")
);


exports.saveSellerPortfolioItem = (event, context, callback) => 

    context.callbackWaitsForEmptyEventLoop = false;

    if (event.body == null && event.body == undefined) 
        var response = errorCodes.missing_parameters;
        callback(null, response)
    
    else 
        let body = JSON.parse(event.body)
        console.log("body", body);

        let iduser = Number(body.iduser);
        let title = body.title;
        let description = body.description;
     

        if (isNaN(iduser)) 
            var response = errorCodes.invalid_parameter;
            callback(null, response);
        
        else 
            // allows for using callbacks as finish/error-handlers
            const sql = "INSERT INTO seller_portfolio_item (iduser, title, description) VALUES (?,?,?)";
            con.execute(sql, [iduser, title, description], function (err, result) 
                if (err) 
                    console.log(err.toString());

                    if (err.toString().indexOf('cannot be null') >= 0) 
                        var response = errorCodes.not_null_parameters;
                        callback(null, response);
                    
                    var response = errorCodes.internal_server_error;
                    callback(null, response);

                
                else 
                    var response = 
                        "statusCode": 200,
                        "headers": 
                            "Content-Type": "application/json"
                        ,
                        "body": JSON.stringify( insertId: result.insertId ),
                        "isBase64Encoded": false
                    ;
                    callback(null, response)
                
            );
        


    
;

我的代码只能插入一条记录,不适合在发送列表时保存多条。结果,客户端程序将不得不在循环中一次又一次地调用相同的方法。

如何读取列表并插入多条记录?

【问题讨论】:

您可以使用具有多个值的 SQL 字符串:"INSERT INTO seller_portfolio_item (iduser, title, description) VALUES (?,?,?), (?,?,?), (?,?,?)" 我现在无法测试它,但因为mysql2 旨在成为mysql 的替代品,所以How do I do a bulk insert in mySQL using node.js 可能有效。 【参考方案1】:

您说得对,今后最好使用mysql 而不是mysql2。下面是一种可用于批量插入多条记录的方法。

请务必运行npm install mysql --save 以确保您必须安装必要的软件包。

处理多条记录还需要一些额外的思考和计划。您应该考虑:

您的表是否包含除主键之外的任何唯一键? 您的 API 函数是否可能会尝试插入重复项? 如果出现重复应该如何处理? 您是否需要知道创建的每条新记录的插入 ID? 列表中的每个对象是否总是具有相同数量的条目、相同的键和预期值?

根据您对上述注意事项的回答,我在下面提供的示例将需要额外的代码和复杂性。这个例子是这个想法最简单的实现。

// package changed, remember to npm install…
const mysql = require('mysql');

const errorCodes = require('source/error-codes');
const PropertiesReader = require('properties-reader');

const prop = PropertiesReader('properties.properties');

const con = mysql.createPool(
  connectionLimit: 10,
  host: prop.get('server.host') || '127.0.0.1',
  user: prop.get("server.username") || 'local_user',
  password: prop.get("server.password") || 'local_password',
  database: prop.get("server.dbname") || 'local_database',
  multipleStatements: true, // necessary to run chained queries
  charset: 'utf8mb4' // necessary if you might need support for emoji characters - table charset must match
);

exports.saveSellerPortfolioItem = (event, context, callback) => 
  context.callbackWaitsForEmptyEventLoop = false;

  // It is better to check for the existence of your
  // expected request body in the controller stage of
  // your app but I've included this for consistency
  // with your original code.
  let query_object = event.body ? JSON.parse(event.body) : null;
  console.log('query_object', query_object);
  if (!query_object.length) 
    let response = errorCodes.missing_parameters;
    callback(null, response)
  

  else 
    // use the keys of the first object to define the field names.
    // you don't have to use this approach but it provides flexibility
    // if you will not always use the same fields
    let keys = Object.keys(query_object[0]);
    // map the values into a supported format
    let values = query_object.map( obj => keys.map( key => obj[key]));
    let sql = 'INSERT INTO seller_portfolio_item (' + keys.join(',') + ') ?;'
    con.query(sql, values, function(error, results, fields) 
      if (error) callback(null, error);

      // when inserting multiples you will only get back the
      // insert id of the first record. if there are updates
      // due to duplicate keys, you won't even get that.
      // results will look like this:
      console.log(results);
      // Expected output
      // OkPacket 
      //   fieldCount: 0,
      //   affectedRows: 3,
      //   insertId: 1,
      //   serverStatus: 2,
      //   warningCount: 6,
      //   message: '&Records: 3  Duplicates: 0  Warnings: 6',
      //   protocol41: true,
      //   changedRows: 0
      // 

      let response = 
        "statusCode": 200,
        "headers": 
          "Content-Type": "application/json"
        ,
        "body": JSON.stringify( records_inserted: results.affectedRows ),
        "isBase64Encoded": false
      ;
      callback(null, response)
    );
  
;

【讨论】:

以上是关于如何在 NodeJS 中将数据批量插入 MySQL?的主要内容,如果未能解决你的问题,请参考以下文章

nodejs mysql批量插入重复密钥更新

eggjs mysql 批量插入多条

使用 mysql2 和 NodeJs 批量插入会抛出 500

Javascript(NodeJs) - 将数组和对象转换为 mysql 中的批量插入(Sequelize)

在nodejs中插入批量数据的问题

如何在 Java 中将日期插入 MySQL 数据库表?