这是我要执行的示例,问题是我不了解如何在过程中收集所有输出DBMS_OUTPUT.PUT_LINE
。
有两种方法可以做到,我不知道是否有适合我的方法。
该示例摘自以下链接。
名称:dbmsoutput.js
描述:
显示在node-oracledb中显示PL / SQL DBMS_OUTPUT的两种方法。
第二种方法取决于以下PL / SQL对象:
创建或替换类型dorow作为varchar2(32767)的表;
https://blogs.oracle.com/opal/using-dbmsoutput-with-nodejs-and-node-oracledb
'use strict';
var async = require('async');
var oracledb = require('oracledb');
var dbconfig = require('./dbconfig.js');
oracledb.createPool(
dbconfig,
function(err, pool) {
if (err)
console.error(err.message)
else
doit(pool);
});
var doit = function(pool) {
async.waterfall(
[
function(cb) {
pool.getConnection(cb);
},
// Tell the DB to buffer DBMS_OUTPUT
enableDbmsOutput,
// Method 1: Fetch a line of DBMS_OUTPUT at a time
createDbmsOutput,
fetchDbmsOutputLine,
// Method 2: Use a pipelined query to get DBMS_OUTPUT
//createDbmsOutput,
function(conn, cb) {
executeSql(
conn,
"begin NoticiasMasVistas(2018); end;", [], { resultSet: true}, cb);
},
printQueryResults
],
function (err, conn) {
if (err) { console.error("In waterfall error cb: ==>", err, "<=="); }
conn.release(
function (err) {
if (err) console.error(err.message);
let pool = oracledb.getPool();
pool.close(10);
});
}
)
};
var enableDbmsOutput = function (conn, cb) {
conn.execute(
"begin dbms_output.enable(null); end;",
function(err) { return cb(err, conn) });
}
var createDbmsOutput = function (conn, cb) {
conn.execute(
`CREATE OR REPLACE PROCEDURE NoticiasMasVistas(p_anio NUMBER) IS
v_IdPer ej_periodico.IdPer%TYPE;
v_numNoticias INTEGER;
CURSOR cPeriodico IS
SELECT p.Nombre, p.IdPer FROM ej_periodico p;
CURSOR cNoticiasMes IS
SELECT EXTRACT(MONTH FROM n.FechaPub) mes, n.Titular, n.NumVisitas
FROM ej_noticia n
WHERE EXTRACT(YEAR FROM n.FechaPub) = p_anio
AND n.IdPer = v_IdPer
AND n.NumVisitas = (SELECT MAX(n2.NumVisitas)
FROM ej_noticia n2
WHERE EXTRACT(YEAR FROM n2.FechaPub) = p_anio
AND n2.IdPer = n.IdPer
AND EXTRACT(MONTH FROM n2.FechaPub) = EXTRACT(MONTH FROM n.FechaPub));
BEGIN
DBMS_OUTPUT.PUT_LINE('NOTICIAS MAS VISITADAS ' || p_anio);
FOR rPeriodico IN cPeriodico LOOP
DBMS_OUTPUT.PUT_LINE('Perdiodico : ' || rPeriodico.Nombre);
v_IdPer := rPeriodico.IdPer;
v_numNoticias := 0;
FOR rNoticiasMes IN cNoticiasMes LOOP
v_numNoticias := v_numNoticias + 1;
DBMS_OUTPUT.PUT_LINE(' Mes: ' || TO_CHAR(rNoticiasMes.mes,'99') ||
': ' || RPAD(rNoticiasMes.Titular,70));
DBMS_OUTPUT.PUT_LINE(' ' || rNoticiasMes.numVisitas || ' Visitas.');
END LOOP;
IF v_numNoticias = 0 THEN
DBMS_OUTPUT.PUT_LINE(' No se han publicado noticias durante 2018');
END IF;
END LOOP;
END;`,
function(err) { return cb(err, conn) });
}
var fetchDbmsOutputLine = function (conn, cb) {
conn.execute(
"begin NoticiasMasVistas(2018); end;",
{},
function(err, result) {
if (err) {
return cb(err, conn);
} else if (result.outBinds.st == 1) {
return cb(null, conn); // no more output
} else {
console.log(result.outBinds.ln);
return fetchDbmsOutputLine(conn, cb);
}
});
}
var executeSql = function (conn, sql, binds, options, cb) {
conn.execute(
sql, binds, options,
function (err, result) {
if (err)
cb(err, conn)
else
cb(null, conn, result);
});
}
var printQueryResults = function(conn, result, cb) {
if (result.resultSet) {
fetchOneRowFromRS(conn, result.resultSet, cb);
} else if (result.rows && result.rows.length > 0) {
console.log(result.rows);
return cb(null, conn);
} else {
console.log("No results");
return cb(null, conn);
}
}
function fetchOneRowFromRS(conn, resultSet, cb) {
resultSet.getRow( // note: getRows would be more efficient
function (err, row) {
if (err) {
cb(err, conn);
} else if (row) {
console.log(row);
fetchOneRowFromRS(conn, resultSet, cb);
} else {
cb(null, conn);
}
});
}
最佳答案
node-oracledb存储库中有两个可运行的示例:
dbmsoutputgetline.js
dbmsoutputpipe.js
第一个为每行输出调用DBMS_OUTPUT.GET_LINE(),因此它可能比管道示例慢,但是它更简单,因此对于快速测试或输出行数少的地方可能很方便。管道示例可以利用优化的查询代码来一次从数据库中获取多个记录。
自从编写了它们(并创建了博客文章)以来,node-oracledb代码已经成为improved,您可能会发现直接提取甚至单单调用getRow()都足够快,因此可以简化管道示例,如果那是您的问题。
我还建议立即使用异步/等待编程风格,因为这样做通常更容易实现。