Node.JS、异步和 Oracle DB:SQL 次尝试太多

Node.JS, async and Oracle DB: too many SQL attempts

使用如下代码:

async.eachSeries(records, function(record, cb) {
  oracle.executeSql("an sql statement", { param1: val },
  function(err, res) { console.log(err.message); cb(); });
});

我得到错误输出 "SQL exec attempts exceed"。我什至在执行 SQL 语句的第一条记录中得到它。我做错了什么?

2019/06/26 更新:

从 2.2 版开始,驱动程序 built-in 支持批处理 SQL 执行。尽可能使用 connection.executeMany() 。它以较低的复杂性提供了所有性能优势。有关详细信息,请参阅文档的批处理语句执行部分:https://oracle.github.io/node-oracledb/doc/api.html#batchexecution

上一个回答:

处理许多记录时,最好通过编写更多代码和使用批量绑定来限制往返。这是一个例子...

鉴于这些对象:

create table t (
  id    number not null primary key,
  prop1 number not null,
  prop2 varchar2(50) not null
)
/

create sequence t_seq;

以下应该有效:

const oracledb = require('oracledb');
const config = require('./dbConfig.js');

async function insertObjects(objs) {
  const start = Date.now();
  let conn;

  try {
    conn = await oracledb.getConnection(config);

    const prop1s = [];
    const prop2s = [];

    // Split the objects up into separate arrays because the driver
    // currently only supports scalar array bindings.
    for (let idx = 0; idx < objs.length; idx += 1) {
      prop1s.push(objs[idx].prop1);
      prop2s.push(objs[idx].prop2);
    }

    const result = await 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_prop1s number_aat := :prop1s;
          l_prop2s varchar2_aat := :prop2s;
        begin
          forall x in l_prop1s.first .. l_prop1s.last
            insert into t (id, prop1, prop2) values (t_seq.nextval, l_prop1s(x), l_prop2s(x));
        end;`,
      {
        prop1s: {
          type: oracledb.NUMBER,
          dir: oracledb.BIND_IN,
          val: prop1s
        }, 
        prop2s: {
          type: oracledb.STRING,
          dir: oracledb.BIND_IN,
          val: prop2s
        }
      },
      {
        autoCommit: true
      }
    );

    console.log('Success. Inserted ' + objs.length + ' rows in ' + (Date.now() - start) + ' ms.');
  } catch (err) {
    console.error(err);
  } finally {
    if (conn) {
      try {
        await conn.close();
      } catch (err) {
        console.error(err);
      }
    }
  }
}

function getObjects(count) {
  var objs = [];

  for (let idx = 0; idx < count; idx += 1) {
    objs[idx] = {
      prop1: idx,
      prop2: "Thing number " + idx
    };
  }

  return objs;
}

const objs = getObjects(500);

insertObjects(objs);

那使用了驱动程序的执行方法,但你可以适应你的包装器。此外,当我使用 one-off 连接时,大多数应用程序应该使用连接池。

原来错误来自 in-house Oracle 包装器,它有一些问题。使用 Oracle 驱动程序函数直接为我解决了这个问题。