¿Cómo hago una inserción masiva en mySQL usando node.js


123

¿Cómo se haría una inserción masiva en mySQL si se usa algo como https://github.com/felixge/node-mysql


¿cual es tu problema? ¿Puedes hacerlo de la misma manera que con un comando sql? Simplemente inicie el siguiente comando cuando se haya completado previamente hasta que haya insertado todos los datos.
Andrey Sidorov

3
Tenía la impresión de que los insertos a granel son más rápidos que muchos insertos individuales.
crickeys

a nivel de cable son lo mismo. No hay 'inserción masiva' en el protocolo mysql
Andrey Sidorov

1
hay insertar múltiples en mySQL, simplemente use la palabra clave VALUES. dev.mysql.com/doc/refman/5.5/en/insert.html Las instrucciones INSERT que usan la sintaxis VALUES pueden insertar varias filas. Para hacer esto, incluya múltiples listas de valores de columna, cada una encerrada entre paréntesis y separadas por comas. Ejemplo: INSERTAR EN tbl_name (a, b, c) VALUES (1,2,3), (4,5,6), (7,8,9);
crickeys

Respuestas:


288

Las inserciones masivas son posibles mediante el uso de una matriz anidada, consulte la página de github

Las matrices anidadas se convierten en listas agrupadas (para inserciones masivas), por ejemplo, se [['a', 'b'], ['c', 'd']]convierten en('a', 'b'), ('c', 'd')

Simplemente inserta una matriz anidada de elementos.

Aquí se da un ejemplo.

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: valueses una matriz de matrices envueltas en una matriz

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

También hay un paquete node-msql totalmente diferente para la inserción masiva


2
¿Proporciona esto las mismas protecciones que conn.execute()al usar declaraciones preparadas? Si no es así, ¿es posible utilizar declaraciones preparadas al hacer inserciones? Gracias.
Vigs

2
Sí, los valores se escapan con este método. Creo que es el mismo mecanismo que las declaraciones preparadas, que también usa connection.escape () internamente.
Ragnar123

77
Esto me confunde. ¿Por qué la matriz tiene que ser [[['a', 'b'], ['c', 'd']]] y no [['' a ',' b '], [' c ',' d ']] como dice la documentación?
Victorio Berra

12
Victorio Berra, se debe a que la matriz más externa es el único signo de interrogación coincidente en la declaración en general, no solo en la inserción. Por ejemplo, si tuviera dos marcadores de posición de signo de interrogación, tendría [param1, param2]. Diga "¿ACTUALIZAR Usuarios? DONDE ID =?", [Columnas, ID] Entonces, las columnas se expandirán al primer signo de interrogación y el ID al segundo.
Selay

3
Lamentablemente, esta respuesta no me funciona. Literalmente copié tu respuesta pero sin éxito.
Publiqué

19

La respuesta de @ Ragnar123 es correcta, pero veo que mucha gente dice en los comentarios que no está funcionando. Tuve el mismo problema y parece que necesitas envolver tu matriz de []esta manera:

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

Tiene que pasar como [pars]en el método.


66
Sí, por alguna razón tiene que ser una matriz, una matriz de matrices ...
Joe

También parece que requiere un singular en ?lugar de ??obtener la agrupación correcta.
Federico

15

Estaba buscando una respuesta sobre la inserción masiva de objetos.

La respuesta de Ragnar123 me llevó a hacer esta función:

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 eso ayude!


11

Me encontré con esto hoy ( mysql 2.16.0) y pensé en compartir mi solución:

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
Me gusta tu solución
Joe

¡Esta solución funcionó para mí! 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 los accesorios para Ragnar123 por su respuesta.

Solo quería expandirlo después de la pregunta hecha por Josh Harington para hablar sobre las ID insertadas.

Estos serán secuenciales. Vea esta respuesta: ¿una inserción de varias filas de MySQL toma ID de incremento automático secuencial?

Por lo tanto, puede hacer esto (observe lo que hice con el 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);
  });

(Extraje los valores de una matriz de objetos que llamé persistentObjects).

Espero que esto ayude.


¿estamos garantizados que en el caso de los insertos simultáneos la condición de carrera no mezclará los identificadores de inserto?
Purefan

1
@Purefan Según mis pruebas, sí, sin embargo, quién sabe si esto cambiará alguna vez.
thewormsterror

Tenga en cuenta, que esto sólo funciona si el tamaño de paso AUTO_INCREMENT está en su valor original de 1. Véase dev.mysql.com/doc/refman/5.7/en/...
Luksch

6

Este es un rápido "raw-copy-paste" recortado para empujar una columna de archivo en mysql con node.js> = 11

Fila de 250k en pocos 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
Esto funciona increíblemente bien, ¡gracias! Nota para los adaptadores: incluso si tiene varias columnas en INSERT, la clave es mantener esto solo ?después VALUES, sin corchetes. De esta forma, la matriz de matrices de columnas se puede procesar automáticamente en insertos masivos. Lo usó para analizar cientos de megabytes de registros de acceso en MySQL.
Alex Pakka

No me di cuenta por qué estabas rompiendo esto en pedazos hasta que lo intenté sin él. En algún momento, mi inserción se hizo demasiado grande para que el servidor la procesara de manera oportuna y recibí un error EPIPE. Romper el inserto en trozos arregla eso. :)
Kit Peters

4

En caso de que sea necesario, aquí es cómo resolvimos la inserción de la matriz

la solicitud es del cartero (Verá "invitados")

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

Y como escribimos

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

Si Ragnarla respuesta no te funciona. Probablemente, este sea el motivo (según mi experiencia):

  1. No estaba usando el node-mysqlpaquete como se muestra en mi Ragnar. Estaba usando el mysqlpaquete. Son diferentes (si no lo notaste, como yo). Pero no estoy seguro de si tiene algo que ver con el hecho de que ?no funciona, ya que parecía funcionar para muchas personas que usan el mysqlpaquete.

  2. Intenta usar una variable en lugar de ?

Lo siguiente funcionó para mí:

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 esto ayude a alguien.


Creo que podrías olvidarte de poner el [] en valores. También me pasó a mí. Debería ser: conn.query (sql, [values], function () {}) En lugar de: conn.query (sql, values, function () {}) A pesar de que la variable de valores es una matriz, pero todavía tenemos para envolverlo con []
Anh Nguyen

El paquete node-mysql actual tiene una sintaxis totalmente diferente en comparación con el paquete mysql. El enlace del paquete node-mysql es npmjs.com/package/node-mysql El enlace del paquete mysql es github.com/mysqljs/mysql#escaping-query-values
Agnel Vishal

2

Algunas cosas que quiero mencionar es que estoy usando el paquete mysql para hacer una conexión con mi base de datos y lo que viste a continuación es un código de trabajo y está escrito para insertar una consulta masiva.

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

Estaba teniendo un problema similar Simplemente estaba insertando uno de la lista de matrices. Funcionó después de hacer los siguientes cambios.

  1. Pasó [params] al método de consulta.
  2. ¿Cambió la consulta de inserción (a, b) a valores de tabla1 (?) ==> inserción (a, b) a valores de tabla1? . es decir. Se eliminó la parálisis alrededor del signo de interrogación.

Espero que esto ayude. Estoy usando mysql npm.


0

La inserción masiva en Node.js se puede hacer usando el siguiente código. Me he referido a muchos blogs para conseguir este trabajo.

por favor consulte este enlace también. https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

El código de trabajo.

  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 esto te ayudará.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.