Làm cách nào để thực hiện chèn hàng loạt trong mySQL bằng node.js


123

Làm cách nào để thực hiện việc chèn hàng loạt vào mySQL nếu sử dụng một cái gì đó như https://github.com/felixge/node-mysql


vấn đề của bạn là gì? Bạn có thể làm điều đó theo cách tương tự như với một lệnh sql không? Chỉ bắt đầu lệnh tiếp theo khi hoàn thành trước đó cho đến khi bạn chèn tất cả dữ liệu.
Andrey Sidorov

3
Tôi có ấn tượng rằng Chèn số lượng lớn nhanh hơn nhiều lần chèn đơn lẻ.
crickeys

trên mức dây, chúng giống nhau. Không có 'số lượng lớn chèn' trong giao thức mysql
Andrey Sidorov

1
có chèn nhiều trong mySQL, bạn chỉ cần sử dụng từ khóa VALUES. dev.mysql.com/doc/refman/5.5/en/insert.html Các câu lệnh CHÈN sử dụng cú pháp GIÁ TRỊ có thể chèn nhiều hàng. Để làm điều này, hãy bao gồm nhiều danh sách giá trị cột, mỗi giá trị được đặt trong dấu ngoặc đơn và được phân tách bằng dấu phẩy. Ví dụ: INSERT INTO tbl_name (a, b, c) VALUES (1,2,3), (4,5,6), (7,8,9);
crickeys,

Câu trả lời:


288

Có thể chèn hàng loạt bằng cách sử dụng mảng lồng nhau, xem trang github

Các mảng lồng nhau được chuyển thành danh sách được nhóm lại (đối với chèn hàng loạt), ví dụ: [['a', 'b'], ['c', 'd']]biến thành('a', 'b'), ('c', 'd')

Bạn chỉ cần chèn một mảng các phần tử lồng nhau.

Một ví dụ được đưa ra ở đây

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

Lưu ý: valueslà một mảng các mảng được bao bọc trong một mảng

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

Ngoài ra còn có một gói node-msql hoàn toàn khác để chèn hàng loạt


2
Điều này có cung cấp các biện pháp bảo vệ tương tự như việc conn.execute()sử dụng các báo cáo đã chuẩn bị sẵn không? Nếu không, có thể sử dụng các câu lệnh đã chuẩn bị khi thực hiện chèn không? Cảm ơn.
Vigs

2
Có, các giá trị được thoát bằng phương thức này. Tôi nghĩ rằng đó là cơ chế tương tự như các câu lệnh đã chuẩn bị, cũng sử dụng nội bộ connect.escape ().
Ragnar123

7
Điều này là khó hiểu đối với tôi. Tại sao mảng phải là [[['a', 'b'], ['c', 'd']]] mà không phải là [['a', 'b'], ['c', 'd ']] như tài liệu nói?
Victorio Berra

12
Victorio Berra, đó là vì mảng ngoài cùng là mảng phù hợp với dấu hỏi trong câu lệnh nói chung, không chỉ trong phần chèn. Ví dụ: nếu bạn có hai chỗ dành sẵn dấu chấm hỏi, thì bạn sẽ có [param1, param2]. Nói "CẬP NHẬT người dùng? WHERE ID =?", [Cột, ID] Vì vậy, các cột sẽ được mở rộng cho dấu hỏi đầu tiên và ID cho dấu hỏi thứ hai.
Selay

3
Thật không may, câu trả lời này không phù hợp với tôi. Tôi thực sự đã sao chép câu trả lời của bạn nhưng không thành công. Tôi đã đăng một câu hỏi khác trên stackoverflow.com/questions/41170849/…
Ivan Pandžić

19

@ Ragnar123 câu trả lời là chính xác, nhưng tôi thấy nhiều người nói trong các bình luận rằng nó không hoạt động. Tôi đã gặp vấn đề tương tự và có vẻ như bạn cần kết hợp mảng của mình []như sau:

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]
];

Nó cần phải được chuyển giống như [pars]vào phương thức.


6
Vâng, đối với một số lý do nó cần phải được một mảng, một mảng của mảng ...
Joe

Cũng có vẻ như nó yêu cầu một số ít ?thay vì ??để có được nhóm chính xác.
Federico

15

Tôi đang tìm kiếm câu trả lời về việc chèn hàng loạt Đối tượng.

Câu trả lời của Ragnar123 đã dẫn tôi đến việc tạo ra chức năng này:

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

Hy vọng nó giúp!


11

Tôi đã gặp phải vấn đề này hôm nay ( mysql 2.16.0) và nghĩ rằng tôi sẽ chia sẻ giải pháp của mình:

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
Tôi thích giải pháp của bạn
Joe

Giải pháp này đã làm việc cho tôi! TY! POSTMAN: [{"textQuestionBuilderID": "5", "applicationID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "6", "applicationID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "7", "applicationID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "8", "applicationID": "ABC123", "resultSelected ":" sfgh "}]
Brian

8

Tất cả các đạo cụ cho Ragnar123 cho câu trả lời của mình.

Tôi chỉ muốn mở rộng nó sau câu hỏi của Josh Harington để nói về các ID được chèn.

Đây sẽ là tuần tự. Hãy xem câu trả lời này: Liệu một MySQL nhiều hàng có chèn các ID tự động tăng tuần tự lấy không?

Do đó, bạn chỉ có thể làm điều này (lưu ý những gì tôi đã làm với 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);
  });

(Tôi đã lấy các giá trị từ một mảng đối tượng mà tôi gọi là dai dẳngObjects.)

Hi vọng điêu nay co ich.


chúng tôi có đảm bảo rằng trong trường hợp chèn đồng thời, điều kiện cuộc đua sẽ không trộn lẫn id chèn?
Purefan

1
@ Purefan Theo thử nghiệm của tôi thì có, tuy nhiên ai biết được liệu điều này có bao giờ thay đổi hay không.
thewormsterror

Lưu ý, rằng điều này sẽ chỉ làm việc nếu kích thước bước auto_increment là về giá trị ban đầu của nó 1. Xem dev.mysql.com/doc/refman/5.7/en/...
luksch

6

Đây là một "raw-copy-paste" nhanh chóng được cắt để đẩy một cột tệp trong mysql với node.js> = 11

250k hàng trong vài giây

'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
Điều này hoạt động tuyệt vời, cảm ơn bạn! Lưu ý đối với bộ điều hợp: ngay cả khi bạn có nhiều cột trong CHÈN, điều quan trọng là giữ nguyên cột này ?sau đó VALUES, không có bất kỳ dấu ngoặc nào. Bằng cách này, mảng các mảng cột có thể được tự động xử lý trong các lần chèn hàng loạt. Đã sử dụng nó để phân tích hàng trăm MB nhật ký truy cập trong MySQL.
Alex Pakka

Tôi đã không nhận ra tại sao bạn lại chia nó thành nhiều phần cho đến khi tôi thử nó mà không. Tại một số thời điểm, chèn của tôi quá lớn để máy chủ xử lý kịp thời và tôi đã gặp lỗi EPIPE. Bẻ miếng chèn thành nhiều miếng sẽ khắc phục điều đó. :)
Kit Peters

4

Trong trường hợp cần thiết, đây là cách chúng tôi giải quyết việc chèn mảng

yêu cầu là từ người đưa thư (Bạn sẽ nhìn vào "khách")

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

Và cách chúng tôi viết kịch bản

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

Nếu Ragnarcâu trả lời không phù hợp với bạn. Đây có lẽ là lý do tại sao (dựa trên kinh nghiệm của tôi) -

  1. Tôi đã không sử dụng node-mysqlgói như được hiển thị Ragnar. Tôi đã sử dụng mysqlgói. Chúng khác nhau (nếu bạn không để ý - giống như tôi). Nhưng tôi không chắc liệu nó có liên quan gì đến việc ?không hoạt động hay không, vì nó dường như hiệu quả với nhiều người sử dụng mysqlgói.

  2. Hãy thử sử dụng một biến thay vì ?

Những điều sau đây đã làm việc cho tôi -

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

Hy vọng điều này sẽ giúp ai đó.


Tôi nghĩ rằng bạn có thể quên đặt [] cho các giá trị. Nó cũng xảy ra với tôi. Nó phải là: conn.query (sql, [giá trị], function () {}) Thay vì: conn.query (sql, giá trị, function () {}) Mặc dù biến giá trị là một mảng, nhưng chúng ta vẫn có để quấn nó với []
Anh Nguyen

Gói node-mysql hiện tại có cú pháp hoàn toàn khác so với gói mysql. liên kết gói node-mysql là npmjs.com/package/node-mysql Liên kết gói mysql là github.com/mysqljs/mysql#escaping-query-values
Agnel Vishal

2

Một vài điều tôi muốn đề cập là tôi đang sử dụng gói mysql để tạo kết nối với cơ sở dữ liệu của mình và những gì bạn thấy bên dưới là mã hoạt động và được viết để chèn truy vấn hàng loạt.

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

Tôi đã gặp vấn đề tương tự. Nó chỉ là chèn một từ danh sách các mảng. Nó hoạt động sau khi thực hiện các thay đổi dưới đây.

  1. Đã chuyển [params] cho phương thức truy vấn.
  2. Thay đổi truy vấn từ insert (a, b) thành table1 giá trị (?) ==> insert (a, b) into table1 value? . I E. Đã xóa phần chú thích xung quanh dấu chấm hỏi.

Hi vọng điêu nay co ich. Tôi đang sử dụng mysql npm.


0

Chèn hàng loạt trong Node.js có thể được thực hiện bằng cách sử dụng đoạn mã dưới đây. Tôi đã tham khảo rất nhiều blog để nhận được công việc này.

xin vui lòng tham khảo liên kết này. https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

Mã làm việc.

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

Hy vọng điều này sẽ giúp bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.