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


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

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

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

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


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.


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!


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) => {...}
);

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.


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

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

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

Espero que isso ajude alguém.


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

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.


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ê.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.