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 驱动程序函数直接为我解决了这个问题。
使用如下代码:
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 驱动程序函数直接为我解决了这个问题。