代码之家  ›  专栏  ›  技术社区  ›  treadmarks

节点。JS、async和Oracle DB:SQL尝试次数太多

  •  0
  • treadmarks  · 技术社区  · 7 年前

    使用如下代码:

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

    我得到错误输出“SQL exec尝试次数超过”。我甚至在执行SQL语句的第一条记录中得到了它。我做错了什么?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Dan McGhan    5 年前

    2019年6月26日更新:

    自版本2.2以来,该驱动程序内置了对批处理SQL执行的支持。使用连接。尽可能执行此操作。它以更少的复杂性提供了所有性能优势。有关更多详细信息,请参阅文档的Batch Statement Execute部分: 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);
    

    它使用驱动程序的execute方法,但您可以调整包装器。此外,虽然我使用一次性连接,但大多数应用程序都应该使用连接池。

        2
  •  0
  •   treadmarks    6 年前

    结果表明,错误来自内部的Oracle包装器,该包装器存在一些问题。使用Oracle驱动程序函数直接修复了这一问题。