定义弱定义的引用游标有问题

时间:2009-06-17 15:16:43

标签: sql oracle

我正在尝试编写一个带有数字n的存储过程,并返回给定查询的前n个结果,专门锁定这n行。我对SQL有点新,我在正确匹配数据类型时遇到了一些困难。

我的包规格如下:

PACKAGE package IS
   Type out_result_type is REF CURSOR;
   PROCEDURE stored_proc
     (in_n IN NUMBER DEFAULT 10, 
        out_list IN OUT out_result_type);

然后我在过程体中定义光标,如下所示:

CURSOR OUT_RESULT_TYPE IS
        SELECT a.id
            FROM schema.table a
            WHERE (some conditions) AND rownum <= in_n;

稍后我会尝试将光标的结果提取到输出变量中:

OPEN OUT_RESULT_TYPE;
FETCH OUT_RESULT_TYPE INTO out_list; -- error on this line
CLOSE OUT_RESULT_TYPE;

但是这个代码没有编译; oracle抱怨out_list已经被定义为具有冲突的数据类型。知道如何解决这个问题吗?这让我发疯了!

提前致谢。

5 个答案:

答案 0 :(得分:1)

CREATE OR REPLACE PACKAGE pkg_test
AS
        TYPE    tt_cur IS REF CURSOR;
        PROCEDURE prc_cur (retval OUT tt_cur);
END;

CREATE OR REPLACE PACKAGE BODY pkg_test
AS
        PROCEDURE prc_cur (retval OUT tt_cur)
        AS
        BEGIN
                OPEN    retval
                FOR
                SELECT  *
                FROM    dual;
        END;
END;

如果您想锁定,请使用:

CREATE OR REPLACE PACKAGE BODY pkg_test
AS
        PROCEDURE prc_cur (retval OUT tt_cur)
        AS
        BEGIN
                OPEN    retval
                FOR
                SELECT  a.id
                FROM    schema.table a
                WHERE   (some conditions)
                        AND rownum <= in_n
                ORDER BY
                        column
                -- Never forget ORDER BY!
                FOR UPDATE;
        END;
END;

答案 1 :(得分:0)

您的out_list类型必须错误。考虑(脚本在10.2.0.3上运行):

CREATE TABLE t AS SELECT ROWNUM ID FROM all_objects WHERE ROWNUM <= 100;

CREATE OR REPLACE PACKAGE cursor_pck AS
   TYPE out_result_type is REF CURSOR;
   PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
                          p_out_list IN OUT out_result_type);
END cursor_pck;
/

如果要同时选择并锁定行,可以使用FOR UPDATE子句:

CREATE OR REPLACE PACKAGE BODY cursor_pck AS
   PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10,  
                          p_out_list IN OUT out_result_type) IS
   BEGIN
      OPEN p_out_list FOR SELECT a.id FROM t a WHERE ROWNUM <= p_in FOR UPDATE;
   END stored_proc;
END cursor_pck;
/

通过以下设置,您将调用以下过程:

SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
  2     l_cursor cursor_pck.out_result_type;
  3     l_id t.id%TYPE;
  4  BEGIN
  5     cursor_pck.stored_proc(3, l_cursor);
  6     LOOP
  7        FETCH l_cursor INTO l_id;
  8        EXIT WHEN l_cursor%NOTFOUND;
  9        dbms_output.put_line(l_id);
 10     END LOOP;
 11  END;
 12  /

1
2
3

PL/SQL procedure successfully completed

答案 2 :(得分:0)

两个评论:

  1. 游标未锁定。
  2. 您不必执行Type out_result_type is REF CURSOR;,使用默认类型sys_refcursor。见这里:Oracle - How to have an out ref cursor parameter in a stored procedure?

答案 3 :(得分:0)

这不会按照它的编写方式工作,因为

  1. out_list需要游标,而不是游标结果。
  2. 名称out_result_type已用于类型,因此您无法将其重新定义为同一范围内的光标

答案 4 :(得分:0)

Oracle提供了一个预定义的弱引用游标:sys_refcursor。在使用中它看起来像:

CREATE OR REPLACE PACKAGE pkg_test
AS
    PROCEDURE prc_cur (p_retval OUT sys_refcursor,
                       p_lookup IN  VARCHAR2);
END pkg_test;


CREATE OR REPLACE PACKAGE BODY pkg_test 
AS
    PROCEDURE prc_cur(p_retval OUT sys_refcursor
                      p_lookup IN  VARCHAR2) 
    IS
    BEGIN
        OPEN retval FOR SELECT a.value 
                          FROM tblname a 
                         WHERE a.id <= p_lookup;
    END prc_cur;
END pkg_test;

这样可以省去需要声明类型的麻烦。 sys_refcursor是指向打开游标的结果集的指针。如果您熟悉Java,它与java.sql.ResultSet对象的概念相同,它提供了一种获取查询结果的方法。

相关问题