如何在 Oracle 中将动态 sql 执行到游标中?

How to execute dynamic sql into cursor in Oracle?

我在存储过程中将动态 sql 语句执行到 sys_refcursor 时遇到问题。 我查看了文档,我认为我正确地构建了我的程序,但我仍然不知道为什么会发生错误。 请看下面,我创建的内容:

CREATE TABLE REKOM_CROSS_PROM (
      LINIA_PROD VARCHAR2(20), 
      ID_REKOM_OFERTA VARCHAR2(20),
      PRICE NUMBER,
      MAX_PRICE NUMBER
    );
/

CREATE OR REPLACE TYPE prodType AS OBJECT (
p_line VARCHAR2(20)
,p_price NUMBER
);
/

CREATE OR REPLACE TYPE prodTypeList IS TABLE OF prodType;
/

CREATE OR REPLACE PROCEDURE my_proc (prodLines IN prodTypeList ,rekom OUT SYS_REFCURSOR)
IS
v_pLine VARCHAR2(20);
v_query VARCHAR2(4000);
BEGIN
  v_query := 'SELECT ID_REKOM_OFERTA FROM REKOM_CROSS_PROM WHERE 
LINIA_PROD=NULL';
FOR i IN 1 .. prodLines.COUNT
    LOOP
        v_pLine := prodLines(i).p_line;
        v_query := v_query || ' UNION ALL SELECT ID_REKOM_OFERTA FROM 
                    REKOM_CROSS_PROM WHERE LINIA_PROD=''' || v_pLine || '''';
    END LOOP;
OPEN rekom FOR v_query;
END my_proc;
/

当我想调用程序时,出现错误。

set serveroutput on
    declare
    type1 prodTypeList := prodTypeList(prodType('test1',1), prodType('test2', 20));
    rc SYS_REFCURSOR;
    row varchar2(200);
BEGIN
    MY_PROC(type1, rc);
    fetch rc into row;
    while (rc%found) loop
    dbms_output.put_line(row);
end loop;
close rc;
end;

我收到消息:

ORA-20000: ORU-10027: 缓冲区溢出,限制为 1000000 字节

*原因:存储过程'raise_application_error' 被调用导致生成此错误。

*操作:按照错误消息或联系方式中所述更正问题 应用程序管理员或 DBA 以获取更多信息。

有人可以帮我解决这个问题吗?

你有一个无限循环。这意味着您将永远调用 dbms_output.put_line - 或者直到它用完缓冲区 space 并抛出该异常。

BEGIN
  MY_PROC(type1, rc);
  -- fetch first row from result set
  fetch rc into row;
  -- check if last fetch found something - always true
  while (rc%found) loop
    dbms_output.put_line(row);
  end loop;
  close rc;
end;

每次循环时,您都在检查第一次提取的结果,它保持为真(假设有任何数据)。每次循环都需要获取:

BEGIN
  MY_PROC(type1, rc);
  -- fetch first row from result set
  fetch rc into row;
  -- check if last fetch found something
  while (rc%found) loop
    dbms_output.put_line(row);
    -- fetch next row from result set
    fetch rc into row;
  end loop;
  close rc;
end;

或者更常见的是,只在循环内部获取,并在找不到任何内容时停止,使用 %notfound 而不是 %found:

BEGIN
  MY_PROC(type1, rc);
  loop
    -- fetch row from result set
    fetch rc into row;
    -- check if last fetch found something
    exit when rc%notfound;
    dbms_output.put_line(row);
  end loop;
  close rc;
end;

与您当前的问题无关,但谓词 WHERE LINIA_PROD=NULL 永远不会为真; null 不等于(或不等于)任何其他内容。您需要改用 WHERE LINIA_PROD IS NULL