Node.js kullanarak mySQL'de nasıl toplu ekleme yaparım


123

Https://github.com/felixge/node-mysql gibi bir şey kullanılıyorsa, mySQL'e toplu ekleme nasıl yapılır?


Senin problemin ne? Bunu bir sql komutuyla aynı şekilde yapabilir misiniz? Tüm verileri girene kadar önceki tamamlandığında bir sonraki komutu başlatın.
Andrey Sidorov

3
TOPLU Uçların birçok tekli kesici uçtan daha hızlı olduğu izlenimine kapıldım.
crickeys

tel seviyesinde onlar aynı. Mysql protokolünde 'toplu ekleme' yoktur
Andrey Sidorov

1
mySQL'de birden fazla ekleyin, yalnızca VALUES anahtar sözcüğünü kullanın. dev.mysql.com/doc/refman/5.5/en/insert.html VALUES sözdizimini kullanan INSERT deyimleri birden çok satır ekleyebilir. Bunu yapmak için, her biri parantez içine alınmış ve virgülle ayrılmış birden çok sütun değeri listesi ekleyin. Örnek: INSERT INTO tbl_name (a, b, c) VALUES (1,2,3), (4,5,6), (7,8,9);
crickeys

Yanıtlar:


288

İç içe dizi kullanılarak toplu eklemeler mümkündür, github sayfasına bakın

İç içe diziler, (kütle parçaları için) gruplandırılmış listeler halinde, örneğin getirilir [['a', 'b'], ['c', 'd']]içine döner('a', 'b'), ('c', 'd')

Yalnızca iç içe geçmiş bir öğe dizisi eklersiniz.

Bir örnek verilmiştir burada

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

Not: valuesbir dizi içine sarılmış bir dizi dizisidir

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

Toplu ekleme için tamamen farklı bir node-msql paketi de var


2
Bu, conn.execute()hazırlanmış ifadeleri kullanmakla aynı korumaları sağlıyor mu ? Değilse, ekler yaparken hazırlanmış ifadelerden yararlanmak mümkün müdür? Teşekkürler.
Vigs

2
Evet, bu yöntemle değerlerin dışına çıkılır. Bunun dahili olarak connection.escape () kullanan hazırlanmış ifadelerle aynı mekanizma olduğunu düşünüyorum.
Ragnar123

7
Bu benim için kafa karıştırıcı. Neden dizi [[['a', 'b'], ['c', 'd']]] olmak zorunda ve [['a', 'b'], ['c', 'd değil ']] belgelerin dediği gibi?
Victorio Berra

12
Victorio Berra, bunun nedeni, en dıştaki dizinin, yalnızca eklemede değil, genel olarak ifadedeki tek eşleşen soru işareti olmasıdır. Örneğin, iki soru işareti yer tutucunuz varsa, [param1, param2] 'ye sahip olurdunuz. "UPDATE Users? NEREDE KİMLİĞİ =?", [Sütunlar, KIMLIK] deyin. Böylece, sütunlar ilk soru işaretine ve kimlik ikinci soru işaretine genişletilecektir.
Selay

3
Maalesef bu cevap benim için çalışmıyor. Cevabınızı tam anlamıyla kopyaladım ama başarılı olamadım. Ben başka bir soru haberi stackoverflow.com/questions/41170849/...
Ivan Pandziç

19

@ Ragnar123 yanıtı doğru, ancak yorumlarda işe yaramadığını söyleyen birçok insan görüyorum. Aynı sorunu yaşadım ve dizinizi şu şekilde sarmalamanız gerekiyor gibi görünüyor []:

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

Metoda olduğu gibi geçilmesi gerekiyor [pars].


6
Evet, bazı nedenlerden dolayı bir dizi dizi olması gerekiyor ...
Joe

Ayrıca doğru gruplamayı elde etmek ?yerine tekil olması gerektiği gibi görünüyor ??.
Federico

15

Nesneleri toplu olarak ekleme konusunda bir cevap arıyordum.

Ragnar123'ün cevabı beni bu işlevi yapmaya yönlendirdi:

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

Umarım yardımcı olur!


11

Bugün bununla karşılaştım ( mysql 2.16.0) ve çözümümü paylaşacağımı düşündüm:

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
Çözümünüzü beğendim
Joe,

Bu çözüm benim için çalıştı! TY! POSTMAN: [{"textQuestionBuilderID": "5", "candidateID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "6", "candidateID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "7", "candidateID": "ABC123", "resultSelected": "sfgh"}, {"textQuestionBuilderID": "8", "candidateID": "ABC123", "sonuç seçildi ":" sfgh "}]
Brian

8

Hepsi cevabı için Ragnar123'ü destekliyor.

Josh Harington tarafından eklenen kimlikler hakkında konuşmak için sorulan sorudan sonra genişletmek istedim.

Bunlar sıralı olacaktır. Şu yanıta bakın: MySQL çok sıralı eklenti sıralı otomatik artış kimlikleri alır mı?

Dolayısıyla, bunu yapabilirsiniz (result.insertId ile ne yaptığıma dikkat edin):

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

(KalıcıObjects adını verdiğim bir dizi nesneden değerleri çektim.)

Bu yardımcı olur umarım.


Eşzamanlı yerleştirmeler durumunda, yarış koşulunun ek kimliklerini karıştırmayacağına dair garanti var mı?
Purefan

1
@Purefan Testlerime göre evet, ancak bunun değişip değişmeyeceğini kim bilebilir.
thewormsterror

Bunun yalnızca auto_increment adım boyutu orijinal değeri 1 ise işe yarayacağını unutmayın. Bkz. Dev.mysql.com/doc/refman/5.7/en/…
luksch

6

Bu, node.js> = 11 ile mysql'de bir dosya sütununu aktarmak için kırpılan hızlı bir "ham kopyala-yapıştır" tır.

Birkaç saniyede 250 bin satır

'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
Bu inanılmaz derecede iyi çalışıyor, teşekkürler! Bağdaştırıcılara not: INSERT'te birden çok sütununuz olsa bile, anahtar, bunu parantez olmadan ?sonradan saklamaktır VALUES. Bu şekilde, sütun dizileri otomatik olarak toplu eklemelerde işlenebilir. MySQL'de yüzlerce megabaytlık erişim günlüğünü analiz etmek için kullandı.
Alex Pakka

Onsuz deneyene kadar bunu neden parçalara böldüğünü anlamadım. Bir noktada ekim, sunucunun zamanında işleyemeyeceği kadar büyüdü ve bir EPIPE hatası aldım. Ek parçayı parçalara ayırmak bunu düzeltir. :)
Kit Peters

4

Burada gerekli olması durumunda, dizi eklemeyi nasıl çözdük

postacıdan istek ("misafirlere" bakacaksınız)

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

Ve nasıl senaryo yazdık

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

Eğer Ragnarbireyin cevabı sizin için çalışmaz. Muhtemelen nedeni budur (deneyimlerime dayanarak) -

  1. node-mysqlPaketi gösterildiği gibi kullanmıyordum Ragnar. mysqlPaket kullanıyordum . Farklılar (fark etmediyseniz - tıpkı benim gibi). Ancak ?, mysqlpaketi kullanan birçok kişi için işe yaradığı için çalışmamayla bir ilgisi olup olmadığından emin değilim .

  2. Yerine bir değişken kullanmayı deneyin ?

Aşağıdakiler benim için çalıştı -

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

Umarım bu birine yardımcı olur.


Bence [] 'yi değerlere koymayı unutabilirsiniz. Bana da oldu. Şöyle olmalıdır: conn.query (sql, [değerler], function () {}) Bunun yerine: conn.query (sql, values, function () {}) Değerler değişkeni bir dizi olmasına rağmen, ama yine de [] ile
Anh Nguyen

Mevcut node-mysql paketi, mysql paketine kıyasla tamamen farklı sözdizimine sahiptir. node-mysql paket bağlantısı npmjs.com/package/node-mysql mysql paket bağlantısı github.com/mysqljs/mysql#escaping-query-values
Agnel Vishal

2

Bahsetmek istediğim birkaç şey, veritabanımla bağlantı kurmak için mysql paketini kullanıyorum ve aşağıda gördüğünüz kodun çalışıyor olması ve toplu sorgu eklemek için yazılmış olmasıdır.

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

Ben de benzer bir sorun yaşıyordum. Diziler listesinden bir tane ekliyordu. Aşağıdaki değişiklikleri yaptıktan sonra çalıştı.

  1. Sorgu yöntemine [parametreler] geçti.
  2. Sorguyu insert (a, b) yerine table1 değerlerine (?) ==> insert (a, b) 'yi table1 değerlerine mi değiştirdiniz? . yani. Soru işaretinin etrafındaki parantez kaldırıldı.

Bu yardımcı olur umarım. Mysql npm kullanıyorum.


0

Node.js'de toplu ekleme aşağıdaki kod kullanılarak yapılabilir. Bu işi almak için birçok bloga atıfta bulundum.

lütfen bu bağlantıya da bakın. https://www.technicalkeeda.com/nodejs-tutorials/insert-multiple-records-into-mysql-using-nodejs

Çalışma kodu.

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

Umarım bu sana yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.