Como faço para inserir em massa no mySQL usando node.js

123

Como alguém faria uma inserção em massa no mySQL se usasse algo como https://github.com/felixge/node-mysql

crickeys
fonte
qual é o seu problema? Você pode fazer da mesma maneira que com um comando sql? Basta iniciar o próximo comando quando o anterior tiver sido concluído até você inserir todos os dados.
Andrey Sidorov
3
Fiquei com a impressão de que as pastilhas BULK são mais rápidas do que muitas pastilhas individuais.
crickeys
no nível do fio, eles são iguais. Não existe 'inserção em massa' no protocolo mysql
Andrey Sidorov
1
Se você inserir múltiplos no mySQL, basta usar a palavra-chave VALUES. As instruções dev.mysql.com/doc/refman/5.5/en/insert.html INSERT que usam a sintaxe VALUES podem inserir várias linhas. Para fazer isso, inclua várias listas de valores de coluna, cada uma entre parênteses e separadas por vírgulas. Exemplo: INSERIR NO nome_tabela (a, b, c) VALORES (1,2,3), (4,5,6), (7,8,9);
crickeys

Respostas:

288

Inserções em massa são possíveis usando matriz aninhada, consulte a página do github

Matrizes aninhadas são transformadas em listas agrupadas (para inserções em massa), por exemplo, [['a', 'b'], ['c', 'd']]transformadas em('a', 'b'), ('c', 'd')

Você acabou de inserir uma matriz aninhada de elementos.

Um exemplo é dado aqui

var mysql = require('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();
});

Nota: valuesé uma matriz de matrizes agrupadas em uma matriz

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

Há também um pacote node-msql totalmente diferente para inserção em massa

Ragnar123
fonte
2
Isso fornece as mesmas proteções que o conn.execute()uso de instruções preparadas? Caso contrário, é possível utilizar instruções preparadas ao fazer inserções? Obrigado.
Vigs
2
Sim, os valores são escapados com este método. Eu acho que é o mesmo mecanismo que as declarações preparadas, que também usam connection.escape () internamente.
Ragnar123
7
Isso é confuso para mim. Por que a matriz precisa ser [[['a', 'b'], ['c', 'd']]] e não [['a', 'b'], ['c', 'd ']] como a documentação diz?
Victorio Berra
12
Victorio Berra, é porque a matriz mais externa é aquela que corresponde aos pontos de interrogação na declaração em geral, não apenas na inserção. Por exemplo, se você tivesse dois marcadores de posição de ponto de interrogação, teria [param1, param2]. Diga "ATUALIZAR Usuários? WHERE ID =?", [Colunas, ID] Portanto, as colunas serão expandidas para o primeiro ponto de interrogação e o ID para o segundo.
Selay
3
Infelizmente esta resposta não está funcionando para mim. Eu literalmente copiei sua resposta, mas sem sucesso. Eu postei outra pergunta no stackoverflow.com/questions/41170849/… #
456 Ivan Pandžić
19

@ Ragnar123 resposta está correta, mas vejo muitas pessoas dizendo nos comentários que não está funcionando. Eu tive o mesmo problema e parece que você precisa agrupar sua matriz da []seguinte maneira:

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

Ele precisa ser passado como [pars]no método.

Codendaal
fonte
6
Sim, por algum motivo, ele precisa ser um array, de uma matriz de matrizes ...
Joe
Também parece que requer um singular em ?vez de ??obter o agrupamento correto.
Federico
15

Eu estava procurando uma resposta para inserir objetos em massa.

A resposta de Ragnar123 me levou a fazer esta função:

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

Espero que ajude!

Stephen Gibson
fonte
11

Encontrei isso hoje ( mysql 2.16.0) e pensei em compartilhar minha solução:

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) => {...}
);
SnobOfTheGolfClub
fonte
3
Eu gosto da sua solução
Joe
Esta solução funcionou para mim! TY! POSTMAN: [{"textQuestionBuilderID": "5", "candidatoID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "6", "candidatoID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "7", "candidatoID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "8", "candidatoID": "ABC123", "resultSelected ":" sfgh "}]
Brian
8

Todos apoiam Ragnar123 por sua resposta.

Eu só queria expandi-lo após a pergunta feita por Josh Harington para falar sobre IDs inseridos.

Estes serão sequenciais. Veja esta resposta: Uma linha múltipla do MySQL insere IDs de autoincremento seqüencial?

Portanto, você pode fazer isso (observe o que fiz com o resultado.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);
  });

(Peguei os valores de uma matriz de objetos que chamei de persistentObjects.)

Espero que isto ajude.

thewormsterror
fonte
temos a garantia de que, no caso de inserções simultâneas, a condição de corrida não misturará os IDs de inserção?
precisa saber é
1
@Purefan De acordo com meus testes, sim, porém quem sabe se isso vai mudar?
thewormsterror
Observe que isso só funcionará se o tamanho da etapa auto_increment estiver no valor original de 1. Consulte dev.mysql.com/doc/refman/5.7/en/…
luksch
6

Este é um rápido "raw-copy-paste" cortado para enviar uma coluna de arquivo no mysql com node.js> = 11

Linha de 250k em alguns segundos

'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);
Manuel Spigolon
fonte
1
Isso funciona incrivelmente bem, obrigado! Nota para os adaptadores: mesmo que você tenha várias colunas no INSERT, a chave é manter esta única ?depois VALUES, sem colchetes. Dessa forma, a matriz de matrizes de colunas pode ser processada automaticamente em inserções em massa. Utilizado para analisar centenas de megabytes de logs de acesso no MySQL.
precisa saber é o seguinte
Eu não sabia por que você estava dividindo isso em pedaços até que eu tentei sem isso. Em algum momento, minha inserção ficou grande demais para o servidor processar em tempo hábil e ocorreu um erro EPIPE. Quebrar a pastilha em pedaços corrige isso. :)
Kit Peters
4

Caso seja necessário aqui, é como resolvemos a inserção da matriz

request é de carteiro (você verá "convidados")

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

E como roteirizamos

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;
};
Sam
fonte
2

Se Ragnara resposta não funcionar para você. Aqui está provavelmente o porquê (com base na minha experiência) -

  1. Eu não estava usando o node-mysqlpacote como mostrado na minha Ragnar. Eu estava usando o mysqlpacote. Eles são diferentes (se você não percebeu - assim como eu). Mas não tenho certeza se isso tem alguma coisa a ver com o fato de ?não funcionar, pois parecia funcionar para muitas pessoas usando o mysqlpacote.

  2. Tente usar uma variável em vez de ?

O seguinte funcionou para mim -

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

Espero que isso ajude alguém.

Aswin Ramakrishnan
fonte
Eu acho que você pode esquecer de colocar [] em valores. Isso aconteceu comigo também. Deveria ser: conn.query (sql, [valores], função () {}) Em vez de: conn.query (sql, valores, função () {}) Apesar de a variável values ​​ser uma matriz, ainda temos para envolvê-lo com []
Anh Nguyen
O pacote node-mysql atual possui uma sintaxe totalmente diferente em comparação com o pacote mysql. link do pacote node-mysql é npmjs.com/package/node-mysql link do pacote mysql é github.com/mysqljs/mysql#escaping-query-values
Agnel Vishal
2

Poucas coisas que quero mencionar é que estou usando o pacote mysql para fazer uma conexão com meu banco de dados e o que você viu abaixo é um código de trabalho e escrito para inserir consultas em massa.

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)
});
Sagar
fonte
1

Eu estava tendo um problema semelhante. Estava apenas inserindo um da lista de matrizes. Funcionou depois de fazer as alterações abaixo.

  1. Passou [params] para o método de consulta.
  2. A consulta foi alterada da inserção (a, b) nos valores da tabela1 (?) ==> inserção (a, b) nos valores da tabela1? . ie Removida a parêntese em torno do ponto de interrogação.

Espero que isto ajude. Estou usando o mysql npm.

user1998289
fonte
0

A inserção em massa no Node.js pode ser feita usando o código abaixo. Eu indiquei muitos blogs para obter este trabalho.

consulte este link também. https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

O código de trabalho.

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

Espero que isso ajude você.

Yadhu
fonte