如何通过 SQL Developer 执行带有游标和表 OUT 参数的存储过程?
Posted
技术标签:
【中文标题】如何通过 SQL Developer 执行带有游标和表 OUT 参数的存储过程?【英文标题】:How to execute a stored procedure with cursor and table OUT parameters through SQL Developer? 【发布时间】:2014-07-17 09:10:08 【问题描述】:我无法在 SQL Developer 3.2.20.09 中测试一个包含 2 个特性的 Oracle 存储过程:
用户定义的“光标类型”输出参数 用户定义的“TABLE OF VARCHAR 类型”输出参数。存储过程签名:
TYPE ref_cursor_tst IS REF CURSOR;
TYPE arrWarningCode_tst IS TABLE OF VARCHAR2 (4000)
INDEX BY BINARY_INTEGER;
PROCEDURE SP_ITF_CU_DOCUMENT_Test (
p_projectNumber IN VARCHAR2,
p_tag IN VARCHAR2,
p_title IN VARCHAR2,
out_document_curs OUT ref_cursor_tst,
out_errorCode OUT VARCHAR2,
out_arrWarningCode OUT arrWarningCode_tst);
我最终可以得到的最好的测试代码:
set serveroutput on size 100000
DECLARE
docRef VARCHAR2(200);
outDocCurs PD360BADMIN.PKG_ITF_GENERAL_TST.ref_cursor_tst;
outErrorCode VARCHAR2(2000);
arrWarningCodes PD360BADMIN.PKG_ITF_GENERAL_TST.arrWarningCode_tst;
i PLS_INTEGER;
doc TBL_OBJECT%ROWTYPE;
BEGIN
dbms_output.put_line('debut de procedure');
docRef:= 'DOC-012';
arrWarningCodes.DELETE;
--call SP
PKG_ITF_GENERAL_TST.SP_ITF_CU_DOCUMENT_TEST (
p_projectNumber => 'XXX',
p_tag => docRef,
p_title => 'Doc title',
out_document_curs => outDocCurs,
out_errorCode => outErrorCode,
out_arrWarningCode => arrWarningCodes);
--print error code
dbms_output.put_line('out_errorCode=' || outErrorCode);
--print output cursor
--dbms_output.put_line(outDocCurs);
LOOP
FETCH outDocCurs INTO doc;
EXIT WHEN outDocCurs%NOTFOUND;
dbms_output.put_line(doc.OBJ_ID||','||doc.OBJ_TAG);
END LOOP;
--print warnings array
IF arrWarningCodes.count > 0 THEN
FOR i IN arrWarningCodes.FIRST .. arrWarningCodes.LAST LOOP
dbms_output.put_line('warning code=' || arrWarningCodes(i) );
END LOOP;
ENd IF;
dbms_output.put_line('fin de procedure');
END;
/
我得到的错误:
Error report:
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 30
06504. 00000 - "PL/SQL: Return types of Result Set variables or query do not match"
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable
actually refers to during execution.
debut de procedure
out_errorCode=
我几天来一直在测试各种解决方案和语法,并在网上挖掘并寻求不同来源的帮助,但没有成功。
任何线索将不胜感激。
【问题讨论】:
TBL_OBJECT
顾名思义是对象类型的表吗?你能显示对象和表格的定义吗?在设置out_document_curs
的过程中使用的查询是什么 - 是查询同一个表,就像一个简单的select *
?如果可以,你能改变它吗?
【参考方案1】:
假设TBL_OBJECT
是一个具有obj_id
和obj_tag
两个字段的对象类型的表;该程序目前正在执行以下操作:
open out_document_curs for select * from tbl_object;
...那么有两种方法可以完成这项工作。首先是更改要获取的变量以匹配对象字段,而不是对象本身:
DECLARE
...
-- doc TBL_OBJECT%ROWTYPE;
doc_obj_id TBL_OBJECT.OBJ_ID%TYPE;
doc_obj_tag TBL_OBJECT.OBJ_TAG%TYPE;
BEGIN
...
然后更改获取和显示:
LOOP
FETCH outDocCurs INTO doc_obj_id, doc_obj_tag;
EXIT WHEN outDocCurs%NOTFOUND;
dbms_output.put_line(doc_obj_id||','||doc_obj_tag);
END LOOP;
如果对象有更多字段,那么您需要全部定义它们并在 fetch 中指定它们。
另一种是修改过程,使其返回对象类型:
open out_document_curs for select value(t) from tbl_object t;
然后您的调用匿名块将按原样工作,因为简单查询将返回对象本身而不是其中的字段。
您要做什么将取决于该过程的实际使用方式,而不是您的测试调用。
使用一些虚拟设置:
create type doc_obj as object (obj_id number, obj_tag varchar2(10));
/
create table tbl_object of doc_obj;
insert into tbl_object values (doc_obj(1, 'Test'));
还有一个虚拟包体,过程简化为:
PROCEDURE SP_ITF_CU_DOCUMENT_Test (
p_projectNumber IN VARCHAR2,
p_tag IN VARCHAR2,
p_title IN VARCHAR2,
out_document_curs OUT ref_cursor_tst,
out_errorCode OUT VARCHAR2,
out_arrWarningCode OUT arrWarningCode_tst)
IS
BEGIN
open out_document_curs for select value(o) from tbl_object o;
out_errorCode := 'OK';
out_arrWarningCode(1) := 'Danger!';
END SP_ITF_CU_DOCUMENT_Test;
然后完全按照问题中的方式调用您的代码(减去架构名称)给出:
anonymous block completed
debut de procedure
out_errorCode=OK
1,Test
warning code=Danger!
fin de procedure
使用另一种方法,使用对象字段的单个变量,也可以得到相同的结果。
【讨论】:
以上是关于如何通过 SQL Developer 执行带有游标和表 OUT 参数的存储过程?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Oracle PL/SQL 过程的开始部分之后声明游标