Мне нравится Аши sh Ответ Моди, но я не думаю, что он знал, что драйвер уже поддерживает обещания, поэтому его код можно упростить.
Во-первых, вам не нужно getConnection
функция. Функция драйвера getConnection
уже возвращает обещание, если вы не передаете обратный вызов, поэтому эта функция ничего не добавляет.
Функция get
имеет ту же проблему. Он не нужен, потому что метод драйвера execute
уже поддерживает обещания.
Код мог бы выглядеть так:
var XLSX = require("xlsx");
var workbook = XLSX.readFile("Accounts.xlsx");
var sheet_name_list = workbook.SheetNames;
var xlData = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
var connection;
var oracledb = require("oracledb");
oracledb.autoCommit = true;
var dbConfig = require(__dirname + "/dbconfig.js");
async function main() {
const connection = await oracledb.getConnection(dbConfig);
for (i in xlData)
{
var act_fam = xlData[i].ACCOUNT_FAMILY;
const results = await connection.execute(`SELECT * FROM TFAMCORGDS_TEST WHERE MNEFAMCOR='` + act_fam + `'`);
var cnt = results.rows.length;
if (cnt === 0) {
const insertResult = await connection.execute(
`INSERT INTO TFAMCORGDS_TEST (CODFAMCOR,MNEFAMCOR,DATMOD,DATFINACT) VALUES (SCORGDS.NEXTVAL,'` +
act_fam +
`',SYSDATE,NULL)`);
console.log('Rows Inserted: ', insertResult.rowsAffected);
}
}
}
Однако с кодом все еще остаются большие проблемы: SQL Внедрение уязвимостей и чрезмерное количество обращений.
Код в настоящее время использует конкатенацию строк для передачи значений в операторы SQL, что откроет вам SQL проблемы внедрения и производительности. Вместо этого вы должны использовать переменные связывания, как описано здесь: https://oracle.github.io/node-oracledb/doc/api.html#bind
Код будет выглядеть следующим образом:
var XLSX = require("xlsx");
var workbook = XLSX.readFile("Accounts.xlsx");
var sheet_name_list = workbook.SheetNames;
var xlData = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
var connection;
var oracledb = require("oracledb");
oracledb.autoCommit = true;
var dbConfig = require(__dirname + "/dbconfig.js");
async function main() {
const connection = await oracledb.getConnection(dbConfig);
for (i in xlData)
{
var act_fam = xlData[i].ACCOUNT_FAMILY;
const results = await connection.execute('SELECT * FROM TFAMCORGDS_TEST WHERE MNEFAMCOR= :act_fam', [act_fam]);
var cnt = results.rows.length;
if (cnt === 0) {
const insertResult = await connection.execute(
'INSERT INTO TFAMCORGDS_TEST (CODFAMCOR,MNEFAMCOR,DATMOD,DATFINACT) VALUES (SCORGDS.NEXTVAL, :act_fam,SYSDATE,NULL)', [act_fam]);
console.log('Rows Inserted: ', insertResult.rowsAffected);
}
}
}
Теперь код прост и безопасен , Вы можете остановиться на этом, если вы работаете всего с несколькими строками (и число не будет расти со временем), а производительность будет хорошей. В противном случае, пожалуйста, продолжайте ...
Текущая реализация делает то, что мы называем построчная или медленная за медленной обработкой. Как разработчик, вы должны стараться избегать чрезмерных сетевых обходов (сеть является худшим видом ввода / вывода). У вас есть два execute
звонка в l oop, так что для каждой итерации l oop.
есть два обхода. С Oracle у вас есть много инструментов, которые можно сократить на раунде поездки, чтобы вы могли использовать разные подходы здесь. Например, вы можете посмотреть executeMany
: https://oracle.github.io/node-oracledb/doc/api.html# -30-base-round-trip
Однако, в этом случае, я думаю, что самый простой подход, вероятно, будет отправлять операторы в базу данных в виде анонимного блока PL / SQL. Это будет выглядеть так:
var XLSX = require("xlsx");
var workbook = XLSX.readFile("Accounts.xlsx");
var sheet_name_list = workbook.SheetNames;
var xlData = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
var connection;
var oracledb = require("oracledb");
oracledb.autoCommit = true;
var dbConfig = require(__dirname + "/dbconfig.js");
async function main() {
const connection = await oracledb.getConnection(dbConfig);
const act_fams = [];
for (i in xlData)
{
act_fams.push(xlData[i].ACCOUNT_FAMILY);
}
await connection.execute(
`declare
type number_aat is table of number
index by pls_integer;
l_act_fam_arr number_aat;
l_count number;
begin
l_act_fam_arr := :act_fam_arr;
for act_fam in 1 .. l_act_fam_arr.count
loop
select count(*)
into l_count
from tfamcorgds_test
where mnefamcor=act_fam;
if l_count = 0
then
insert into tfamcorgds_test (
codfamcor,mnefamcor,datmod,datfinact
) values (scorgds.nextval, act_fam,sysdate,null);
end if;
end loop;
end;`,
{
act_fam_arr: {
type: oracledb.NUMBER,
val: act_fams
}
}
);
}
Я не тестировал этот код, поэтому возможны синтаксические ошибки. Обратите внимание, что первый параметр, который я передаю execute
, - это большая строка кода, блок PL / SQL. Второй параметр - это переменная связывания, представляющая собой массив чисел (я предположил, что ACCOUNT_FAMILY - это число, но при необходимости вы можете легко изменить его на строку).
Код и значения будут отправлены в база данных через единую сеть туда и обратно. Код PL / SQL реализует ту же логику c, которую вы использовали ранее в JavaScript. Если вы запустите тестирование с этим кодом по сравнению с предыдущей версией, вы увидите заметное улучшение производительности (чем больше извлекается строк, тем заметнее будет улучшение).