2012-01-17 38 views
68

Làm thế nào người ta sẽ làm một số lượng lớn chèn vào mySQL nếu sử dụng một cái gì đó giống như https://github.com/felixge/node-mysqlLàm thế nào để làm một số lượng lớn chèn trong mySQL sử dụng Node.js

+0

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? Chỉ cần bắt đầu lệnh tiếp theo khi đã hoàn tất trước đó cho đến khi bạn chèn tất cả dữ liệu. –

+2

Tôi đã ấn tượng rằng BULK Inserts nhanh hơn nhiều lần chèn đơn. – crickeys

+0

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

Trả lời

153

chèn số lượng lớn có thể xảy ra bằng cách sử dụng mảng lồng nhau, xem github page

Các mảng lồng nhau được chuyển thành các danh sách được nhóm (để chèn số lượng lớn), 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 lồng nhau của các phần tử.

Một ví dụ được đưa ra trong here

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

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

Lưu ý: values là một mảng của mảng được bọc trong một mảng

[ [ [...], [...], [...] ] ] 
+1

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

+0

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

+3

Điều này gây nhầm lẫn cho tôi. Tại sao mảng phải là [[['a', 'b'], ['c', 'd']]] và không phải [['a', 'b'], ['c', 'd ']] như tài liệu nói? –

5

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

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

Đây sẽ là tuần tự. Xem câu trả lời này: Does a MySQL multi-row insert grab sequential autoincrement IDs?

Do đó bạn chỉ có thể làm được điều này (chú ý những gì tôi đã làm với các 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 kéo các giá trị từ một mảng của các đối tượng mà tôi gọi là persistentObjects.)

Hy vọng điều này sẽ hữu ích.

+0

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

+1

@Purefan Theo các bài kiểm tra của tôi có, tuy nhiên ai biết nếu điều này sẽ thay đổi. – thewormsterror

+0

Lưu ý rằng điều này sẽ chỉ hoạt động nếu kích thước bước auto_increment là giá trị ban đầu của nó là 1. Xem http://dev.mysql.com/doc/refman/5.7/en/replication-options-master.html#sysvar_auto_increment_increment – luksch

1

Nếu câu trả lời của Ragnar 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-mysql gói như Ragnar tôi. Tôi đang sử dụng gói mysql. Chúng khác nhau (nếu bạn không chú ý - giống như tôi). Nhưng tôi không chắc chắn nếu nó có bất cứ điều gì để làm với ? không làm việc, vì nó dường như làm việc cho nhiều người sử dụng gói mysql.

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

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', '[email protected]', 1], 
    ['john', '[email protected]', 2], 
    ['mark', '[email protected]', 3], 
    ['pete', '[email protected]', 4] 
]; 
conn.query(sql, { params: values}, function(err) { 
    if (err) throw err; 
    conn.end(); 
}); 

Hope this helps một ai đó.

+0

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

2

Trong trường hợp đó cần thiết ở đây là làm sao chúng ta giải quyết chèn của mảng

yêu cầu đến 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à làm thế nào chúng ta 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; 
}; 
7

Tôi chưa thể nhận xét, do đó, sẽ gửi câu trả lời.

@ Ragnar123 câu trả lời là chính xác, nhưng tôi thấy nhiều người trong nhận xét cho biết nó không hoạt động. Tôi đã cùng một vấn đề và nó có vẻ như bạn cần phải quấn mảng của mình trong []

nên

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

nhu cầu để được thông qua như [pars] vào phương pháp này.

Hy vọng điều này sẽ hữu ích.

+1

Vâng, vì một lý do nào đó nó cần phải là một mảng, của một mảng các mảng ... – Joe

2

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

Câu trả lời bởi Ragnar123 dẫn tôi đến làm cho 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ó sẽ giúp!

0

Tôi gặp sự cố 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 bên dưới.

  1. Đã chuyển [params] cho phương thức truy vấn.
  2. Đã thay đổi truy vấn từ chèn (a, b) thành giá trị table1 (?) ==> chèn (a, b) vào giá trị table1? . I E. Loại bỏ dấu ngoặc xung quanh dấu chấm hỏi.

Hy vọng điều này sẽ hữu ích. Tôi đang sử dụng mysql npm.

Các vấn đề liên quan