当没有剩余记录时,从node-oracle db调用的pl/sql过程返回什么?

问题描述 投票:0回答:1

给定一个类似于下面提供的示例的 pl/sql 过程,

const result = await connection.execute(
      `BEGIN
         :ret := no_func(:p1, :p2, :p3);
       END;`,
      {
        p1: 'Chris', 
        p2: 'Jones',
        p3: { dir: oracledb.BIND_OUT, type: oracledb.NUMBER },
        ret: { dir: oracledb.BIND_OUT, type: oracledb.STRING, maxSize: 40 }
      });

    console.log(result.outBinds);
 

我的任务是不断调用该过程,直到没有记录为止。在这种情况下 result.outBinds 的响应是什么? (或者)我应该向循环添加什么条件以继续调用该过程,直到没有剩余?

非常感谢您的帮助。预先感谢。

sql oracle plsql node-oracledb node-oracle
1个回答
0
投票

让我们假设你有一个函数(没有副作用):

CREATE FUNCTION no_func(
  p1 IN  TABLE_NAME.C1%TYPE,
  p2 IN  TABLE_NAME.C2%TYPE,
  p3 OUT TABLE_NAME.C3%TYPE
) RETURN TABLE_NAME.C4%TYPE
IS
  v4 TABLE_NAME.C4%TYPE;
BEGIN
  SELECT c3, c4
  INTO   p3, v4
  FROM   TABLE_NAME
  WHERE  c1 = p1
  AND    c2 = p2
  FETCH FIRST ROW ONLY;

  RETURN v4;
END;
/

和数据:

CREATE TABLE table_name (c1, c2, c3, c4) AS
SELECT 'Chris', 'Jones', 1, 2 FROM DUAL UNION ALL
SELECT 'Chris', 'Jones', 3, 4 FROM DUAL UNION ALL
SELECT 'Chris', 'Jones', 5, 6 FROM DUAL UNION ALL
SELECT 'Amber', 'Abbot', 7, 8 FROM DUAL;

然后如果你不断调用该函数:

DECLARE
  p1  TABLE_NAME.C1%TYPE := 'Chris';
  p2  TABLE_NAME.C2%TYPE := 'Jones';
  p3  TABLE_NAME.C3%TYPE;
  ret TABLE_NAME.C4%TYPE;
BEGIN
  FOR i IN 1 .. 5 LOOP
    ret := no_func(p1, p2, p3);
    DBMS_OUTPUT.PUT_LINE(p3 || ', ' || ret);
  END LOOP;
END;
/

它输出:

1, 2
1, 2
1, 2
1, 2
1, 2

(注意:如果您不断从 NodeJS 或任何其他客户端应用程序调用它,也会发生同样的情况。)

它不会获取下一条记录,它只是重复相同的第一条记录。除非你的函数有副作用或者依赖于存储在包中的某些外部状态或类似的东西(不要做其中任何一个),那么当你第一次调用该函数时,你可能会得到准确的结果与您第 nth 次调用它时的结果相同。 永远不会出现最初有一行然后没有剩余行的情况,因为函数将重复返回初始结果。

如果调用该函数并且没有找到行:

DECLARE p1 TABLE_NAME.C1%TYPE := 'Bella'; p2 TABLE_NAME.C2%TYPE := 'Baron'; p3 TABLE_NAME.C3%TYPE; ret TABLE_NAME.C4%TYPE; BEGIN ret := no_func(p1, p2, p3); END; /

然后你会得到异常:

ORA-01403: no data found


我的任务是不断调用该过程,直到没有记录为止。

为此,请修改该函数,使其返回一个游标,然后从游标中读取所有匹配的行:

CREATE OR REPLACE FUNCTION no_func( p1 IN TABLE_NAME.C1%TYPE, p2 IN TABLE_NAME.C2%TYPE ) RETURN SYS_REFCURSOR IS cur SYS_REFCURSOR; BEGIN OPEN cur FOR SELECT c3, c4 FROM TABLE_NAME WHERE c1 = p1 AND c2 = p2; RETURN cur; END; /

然后:

DECLARE p1 TABLE_NAME.C1%TYPE := 'Chris'; p2 TABLE_NAME.C2%TYPE := 'Jones'; p3 TABLE_NAME.C3%TYPE; p4 TABLE_NAME.C4%TYPE; cur SYS_REFCURSOR; BEGIN cur := no_func(p1, p2); LOOP FETCH cur INTO p3, p4; EXIT WHEN cur%NOTFOUND; DBMS_OUTPUT.PUT_LINE(p3 || ', ' || p4); END LOOP; END; /

输出:

1, 2 3, 4 5, 6
您可以在 NodeJS 中执行类似操作(基于 

REF CURSOR 绑定参数文档

) - 未经测试,因为我没有用于测试 NodeJS 代码的模式):
const result = await connection.execute( `"BEGIN :cursor := no_func(:p1, :p2); END;`, { p1: "Chris", p1: "Jones", cursor: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT } }, { prefetchRows: 1000, // tune the internal getRow() data fetch performance fetchArraySize: 1000 } ); const resultSet = result.outBinds.cursor; let row; while ((row = await resultSet.getRow())) { console.log(row); } await resultSet.close(); // always close the ResultSet

	
© www.soinside.com 2019 - 2024. All rights reserved.