使用Node.js如何向Oracle数据库插入多条记录

3
我能够向表中插入一条记录,但我想一次性插入多条记录到表中-
下面是我的代码-
var doinsert_autocommit = function (conn, cb) {
var query="INSERT INTO test VALUES (:id,:name)";
var values=[{1,'rate'},{5,'ratee'}]; 

如果我使用[1,'rat'],它可以成功插入一行。
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);
  }
});

};

3个回答

3

请查看在node-oracledb 2.2中引入的executeMany()方法。该方法可执行一个语句,包含多个数据值,通常比多次调用execute()性能更好。

例如:

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

请查看node-oracledb文档中的批量语句执行和批量加载部分。

2

更新于2019/04/25:

自版本2.2起,该驱动程序已内置批量SQL执行支持。尽可能使用connection.executeMany()进行操作,它提供了所有性能优势且更简单易懂。有关更多详细信息,请参见文档中的批处理语句执行部分:https://oracle.github.io/node-oracledb/doc/api.html#batchexecution

之前的回答:

目前,该驱动程序仅支持与PL/SQL一起使用的数组绑定,不支持直接SQL。我们希望将来能够改进这一点。目前,您可以执行以下操作...

给定此表:

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

以下内容应该有效:
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.');
    }
  );
});

这将通过单个往返数据库来插入500行。此外,SQL和PL/SQL引擎之间只有一个上下文切换。

正如您所看到的,数组必须分别绑定(无法绑定对象数组)。这就是为什么示例演示了如何将它们拆分成单独的数组以进行绑定。随着时间的推移,这些操作都会变得更加优雅,但现在这样做也可以。


我对executeMany感到困惑,但是你的代码包含了conn.execute( - Toolkit

-1

我使用了simple-oracledb库进行批量插入,它是oracledb模块的扩展。

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

请注意,虽然方法名称为batchInsert,但实际上操作是分别完成的。如果性能很重要,请参阅我对此问题的答案。 - Dan McGhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接