如何通过SQL Developer执行带游标和表OUT参数的存储过程?

时间:2014-07-17 09:10:09

标签: sql oracle stored-procedures cursor

我在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=

我已经测试了几天的各种解决方案和语法,以及挖掘网络并需要来自不同来源的帮助但没有成功。

任何线索都会非常感激。

1 个答案:

答案 0 :(得分:0)

假设TBL_OBJECT是某个对象类型的表,其中包含两个字段obj_idobj_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

使用另一种方法,使用对象字段的各个变量,也会得到相同的结果。