简体   繁体   中英

How to insert multiple records into Oracle DB using Node.js

I am able to insert one record into a table, but i want to insert multiple records at once into the table-

My Code is below-

var doinsert_autocommit = function (conn, cb) {
var query="INSERT INTO test VALUES (:id,:name)";
var values=[{1,'rate'},{5,'ratee'}]; 

If i use [1,'rat']- its working for inserting one row.

conn.execute(

"INSERT INTO test VALUES (:id,:name)",
values, // Bind values
{ autoCommit: true},  // Override the default non-autocommit behavior
function(err, result)
{
  if (err) {
    return cb(err, conn);
  } else {
    console.log("Rows inserted: " + result.rowsAffected);  // 1
    return cb(null, conn);
  }
});

};

Update 2019/04/25:

The driver, since version 2.2, has built-in support for batch SQL execution. Use connection.executeMany() for this when possible. It offers all of the performance benefits with less complexity. See the Batch Statement Execute section of the documentation for more details: https://oracle.github.io/node-oracledb/doc/api.html#batchexecution

Previous answer:

Currently, the driver only supports array binds with PL/SQL, not direct SQL. We hope to improve this in the future. For now, you can do the following...

Given this table:

create table things (
  id   number not null,
  name varchar2(50) not null
)
/

The following should work:

var oracledb = require('oracledb');
var config = require('./dbconfig');
var things = [];
var idx;

function getThings(count) {
  var things = [];

  for (idx = 0; idx < count; idx += 1) {
    things[idx] = {
      id: idx,
      name: "Thing number " + idx
    };
  }

  return things;
}

// Imagine the 'things' were fetched via a REST call or from a file.
// We end up with an array of things we want to insert.
things = getThings(500);

oracledb.getConnection(config, function(err, conn) {
  var ids = [];
  var names = [];
  var start = Date.now();

  if (err) {throw err;}

  for (idx = 0; idx < things.length; idx += 1) {
    ids.push(things[idx].id);
    names.push(things[idx].name);
  }

  conn.execute(
    ` declare
        type number_aat is table of number
          index by pls_integer;
        type varchar2_aat is table of varchar2(50)
          index by pls_integer;

        l_ids   number_aat := :ids;
        l_names varchar2_aat := :names;
      begin
        forall x in l_ids.first .. l_ids.last
          insert into things (id, name) values (l_ids(x), l_names(x));
      end;`,
    {
      ids: {
        type: oracledb.NUMBER,
        dir: oracledb.BIND_IN,
        val: ids
      }, 
      names: {
        type: oracledb.STRING,
        dir: oracledb.BIND_IN,
        val: names
      }
    },
    {
      autoCommit: true
    },
    function(err) {
      if (err) {console.log(err); return;}

      console.log('Success. Inserted ' + things.length + ' rows in ' + (Date.now() - start) + ' ms.');
    }
  );
});

That will insert 500 rows with a single roundtrip to the database. Plus, a single context switch between the SQL and PL/SQL engines in the DB.

As you can see, the arrays have to be bound in separately (you can't bind an array of objects). That's why the example demonstrates how to break them up into separate arrays for binding purposes. This should all get more elegant over time, but this works for now.

Checkout theexecuteMany() method introduced in node-oracledb 2.2. This executes one statement with many data value, generally with significant performance benefit over calling execute() many times.

For example:

const sql = `INSERT INTO mytab VALUES (:a, :b)`;

const binds = [
  { a: 1, b: "One" },
  { a: 2, b: "Two" },
  { a: 3, b: "Three" }
];

const options = {
  autoCommit: true,
  bindDefs: {
    a: { type: oracledb.NUMBER },
    b: { type: oracledb.STRING, maxSize: 5 }
  }
};

const result = await connection.executeMany(sql, binds, options);

console.log(result.rowsAffected);  // 3

See the node-oracledb documentation Batch Statement Execution and Bulk Loading .

I used the simple-oracledb library for batch insert, its extending the oracledb module.

var async = require('async');
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
var SimpleOracleDB = require('simple-oracledb');

SimpleOracleDB.extend(oracledb);
 var doconnect = function(cb) {
 oracledb.getConnection(
 {
   user          : dbConfig.user,
   password      : dbConfig.password,
   connectString : dbConfig.connectString
 },
 cb);
};

var dorelease = function(conn) {
conn.close(function (err) {
if (err)
  console.error(err.message);
});
};
var doinsert_autocommit = function (conn, cb) {

conn.batchInsert(
 "INSERT INTO test VALUES (:id,:name)",
 [{id:1,name:'nayan'},{id:2,name:'chaan'},{id:3,name:'man'}], // Bind values
 { autoCommit: true},  // Override the default non-autocommit behavior
 function(err, result)
 {
   if (err) {
    return cb(err, conn);
  } else {
    console.log("Rows inserted: " + result.rowsAffected);  // 1
    return cb(null, conn);
  }
});
};


async.waterfall(
[
 doconnect,
 doinsert_autocommit,

],
function (err, conn) {
if (err) { console.error("In waterfall error cb: ==>", err, "<=="); }
if (conn)
  dorelease(conn);
 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM