Bagaimana cara melakukan penyisipan massal di mySQL menggunakan node.js

123

Bagaimana seseorang melakukan penyisipan massal ke mySQL jika menggunakan sesuatu seperti https://github.com/felixge/node-mysql

crickeys
sumber
apa masalahmu? Bisakah Anda melakukannya dengan cara yang sama seperti dengan satu perintah sql? Mulai saja perintah berikutnya saat sebelumnya selesai sampai Anda memasukkan semua data.
Andrey Sidorov
3
Saya mendapat kesan bahwa Sisipan BULK lebih cepat daripada banyak sisipan tunggal.
crickeys
pada level kabel mereka sama. Tidak ada 'penyisipan massal' dalam protokol mysql
Andrey Sidorov
1
ada masukkan beberapa di mySQL, Anda cukup menggunakan kata kunci VALUES. dev.mysql.com/doc/refman/5.5/en/insert.html Pernyataan INSERT yang menggunakan sintaks VALUES dapat menyisipkan beberapa baris. Untuk melakukannya, sertakan beberapa daftar nilai kolom, masing-masing diapit dalam tanda kurung dan dipisahkan dengan koma. Contoh: INSERT INTO tbl_name (a, b, c) VALUES (1,2,3), (4,5,6), (7,8,9);
crickeys

Jawaban:

288

Penyisipan massal dimungkinkan dengan menggunakan array bersarang, lihat halaman github

Array bersarang diubah menjadi daftar yang dikelompokkan (untuk sisipan massal), misalnya [['a', 'b'], ['c', 'd']]berubah menjadi('a', 'b'), ('c', 'd')

Anda cukup menyisipkan larik elemen bersarang.

Contoh diberikan di sini

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

Catatan: valuesadalah larik larik yang dibungkus dalam larik

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

Ada juga paket node-msql yang sangat berbeda untuk penyisipan massal

Ragnar123
sumber
2
Apakah ini memberikan perlindungan yang sama seperti melakukan conn.execute()penggunaan pernyataan yang disiapkan? Jika tidak, apakah mungkin untuk menggunakan pernyataan yang telah disiapkan saat melakukan penyisipan? Terima kasih.
Vigs
2
Ya, nilai di-escape dengan metode ini. Saya pikir ini adalah mekanisme yang sama dengan pernyataan yang disiapkan, yang juga menggunakan koneksi.escape () secara internal.
Ragnar123
7
Ini membingungkan saya. Mengapa array harus [[['a', 'b'], ['c', 'd']]] dan bukan [['a', 'b'], ['c', 'd ']] seperti yang tertulis dalam dokumentasi?
Victorio Berra
12
Victorio Berra, karena larik terluar merupakan tanda tanya yang cocok dalam pernyataan secara umum, tidak hanya di sisipkan. Misalnya, jika Anda memiliki dua placeholder tanda tanya, Anda akan memiliki [param1, param2]. Ucapkan "UPDATE Users? WHERE ID =?", [Kolom, ID] Jadi, kolom akan diperluas ke tanda tanya pertama dan ID ke yang kedua.
Selay
3
Sayangnya jawaban ini tidak berhasil untuk saya. Saya benar-benar menyalin jawaban Anda tetapi tidak berhasil. Saya memposting pertanyaan lain di stackoverflow.com/questions/41170849/…
Ivan Pandžić
19

@ Ragnar123 Jawaban benar, tetapi saya melihat banyak orang mengatakan di komentar bahwa itu tidak berfungsi. Saya memiliki masalah yang sama dan sepertinya Anda perlu membungkus array Anda []seperti ini:

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

Itu perlu diteruskan seperti [pars]ke dalam metode.

Codendaal
sumber
6
Ya, untuk beberapa alasan itu perlu array, dari array ...
Joe
Juga sepertinya itu membutuhkan bentuk tunggal, ?bukan ??untuk mendapatkan pengelompokan yang benar.
Federico
15

Saya mencari-cari jawaban untuk memasukkan Object secara massal.

Jawaban oleh Ragnar123 membuat saya membuat fungsi ini:

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

Semoga membantu!

Stephen Gibson
sumber
11

Saya bertemu hari ini ( mysql 2.16.0) dan berpikir saya akan membagikan solusi saya:

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
sumber
3
Saya suka solusi Anda
Joe
Solusi ini berhasil untuk saya! TY! POSTMAN: [{"textQuestionBuilderID": "5", "kandidatID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "6", "kandidatID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "7", "kandidatID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "8", "kandidatID": "ABC123", "resultSelected ":" sfgh "}]
Brian
8

Semua alat peraga untuk Ragnar123 untuk jawabannya.

Saya hanya ingin mengembangkannya setelah pertanyaan yang diajukan oleh Josh Harington untuk membicarakan tentang ID yang dimasukkan.

Ini akan berurutan. Lihat jawaban ini: Apakah penyisipan multi-baris MySQL mengambil ID autoincrement berurutan?

Karenanya Anda bisa melakukan ini (perhatikan apa yang saya lakukan dengan 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);
  });

(Saya menarik nilai dari array objek yang saya sebut persistentObjects.)

Semoga ini membantu.

thewormsterror
sumber
apakah kami dijamin bahwa dalam kasus sisipan simultan, kondisi balapan tidak akan mencampur ID sisipan?
Purefan
1
@ Purefan Menurut pengujian saya ya, namun siapa yang tahu apakah ini akan berubah.
theormsterror
Perhatikan, ini hanya akan berfungsi jika ukuran langkah auto_increment berada pada nilai aslinya 1. Lihat dev.mysql.com/doc/refman/5.7/en/…
luksch
6

Ini adalah potongan "raw-copy-paste" yang cepat untuk mendorong kolom file di mysql dengan node.js> = 11

250k baris dalam beberapa detik

'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
sumber
1
Ini bekerja dengan sangat baik, terima kasih! Catatan untuk adaptor: bahkan jika Anda memiliki beberapa kolom di SISIPKAN, kuncinya adalah mempertahankan tunggal ini ?setelahnya VALUES, tanpa tanda kurung apa pun. Dengan cara ini, susunan larik kolom dapat diproses secara otomatis dalam sisipan massal. Digunakan untuk menganalisis ratusan megabyte log akses di MySQL.
Alex Pakka
Saya tidak menyadari mengapa Anda memecah ini menjadi beberapa bagian sampai saya mencobanya tanpa. Pada titik tertentu, sisipan saya terlalu besar untuk diproses server tepat waktu dan saya mendapat kesalahan EPIPE. Memecah sisipan menjadi beberapa bagian memperbaikinya. :)
Kit Peters
4

Dalam hal yang dibutuhkan di sini adalah bagaimana kita menyelesaikan penyisipan array

permintaan dari tukang pos (Anda akan melihat "tamu")

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

Dan bagaimana kami membuat naskah

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
sumber
2

RagnarJawaban If tidak berhasil untuk Anda. Ini mungkin alasannya (berdasarkan pengalaman saya) -

  1. Saya tidak menggunakan node-mysqlpaket seperti yang ditunjukkan pada saya Ragnar. Saya menggunakan mysqlpaket. Mereka berbeda (jika Anda tidak menyadarinya - seperti saya). Tapi saya tidak yakin apakah itu ada hubungannya dengan ?tidak berfungsi, karena tampaknya berhasil untuk banyak orang yang menggunakan mysqlpaket tersebut.

  2. Coba gunakan variabel, bukan ?

Berikut ini berhasil untuk saya -

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

Semoga ini bisa membantu seseorang.

Aswin Ramakrishnan
sumber
Saya pikir Anda mungkin lupa meletakkan [] pada nilai. Ini terjadi pada saya juga. Seharusnya: conn.query (sql, [values], function () {}) Alih-alih: conn.query (sql, values, function () {}) Meskipun variabel nilai adalah array, tapi kita masih punya untuk membungkusnya dengan []
Anh Nguyen
Paket node-mysql saat ini memiliki sintaks yang sama sekali berbeda dibandingkan dengan paket mysql. link paket node-mysql adalah npmjs.com/package/node-mysql tautan paket mysql adalah github.com/mysqljs/mysql#escaping-query-values
Agnel Vishal
2

Beberapa hal yang ingin saya sebutkan adalah bahwa saya menggunakan paket mysql untuk membuat koneksi dengan database saya dan apa yang Anda lihat di bawah ini adalah kode yang berfungsi dan ditulis untuk memasukkan kueri massal.

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
sumber
1

Saya mengalami masalah serupa. Itu hanya memasukkan satu dari daftar array. Ini berfungsi setelah melakukan perubahan di bawah ini.

  1. Meneruskan [params] ke metode kueri.
  2. Mengubah kueri dari sisipkan (a, b) menjadi nilai tabel1 (?) ==> sisipkan (a, b) menjadi nilai tabel1? . yaitu. Menghapus paranthesis di sekitar tanda tanya.

Semoga ini membantu. Saya menggunakan mysql npm.

pengguna1998289
sumber
0

Penyisipan massal di Node.js dapat dilakukan menggunakan kode di bawah ini. Saya telah merujuk banyak blog untuk mendapatkan pekerjaan ini.

silakan lihat tautan ini juga. https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

Kode kerja.

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

Semoga ini bisa membantu Anda.

Yadhu
sumber