如何在 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
。
我在存储过程中将动态 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
。