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

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


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