1

我有以下 oracle 存储过程

    CREATE OR REPLACE
PROCEDURE getRejectedReasons
  (
    p_cursor IN OUT SYS_REFCURSOR)
AS
BEGIN
  OPEN p_cursor FOR SELECT * FROM reasons_for_rejection;
END;

但是,当我在 sql-developer 中运行这个存储过程时,我什么也看不到。我只是看到这样的事情:

Connecting to the database oracleLocal.
Process exited.
Disconnecting from the database oracleLocal.

我来自 MS sql 服务器,并且习惯于在运行这样的存储过程时看到实际结果。这个存储过程是否因为我使用游标而没有返回结果?

4

4 回答 4

5

存储过程正在返回一些东西,只是你没有对结果做任何事情。

您只需在 SQLDeveloper 中运行以下脚本即可完成此操作:


VARIABLE csr REFCURSOR;
EXEC getRejectedReasons(:csr); -- the colon identifies the parameter as a variable
PRINT csr;

另一种方法是获取每一行并进行某种处理:


DECLARE
  -- sys_refcursor is weakly typed
  refcsr  SYS_REFCURSOR;
  -- define a record so we can reference the fields
  rej_rec Reasons_for_Rejection%ROWTYPE;
BEGIN

  getRejectedReasons(refcsr);

   -- loop through the results  
   LOOP
      -- gets one row at a time
      FETCH refcsr INTO rej_rec;
      -- if the fetch doesn't find any more rows exit the loop
      EXIT WHEN refcsr%NOTFOUND;
      -- Do something here.  
      -- For example : DBMS_OUTPUT.PUT_LINE(rej_rec.reason_desc);
    END LOOP;

END;
于 2009-05-03T20:46:39.537 回答
1

你打开了光标。您没有从中选择任何内容、更新或推进它。

All open 确实有效地将匹配的行选择到临时内存中,因此您可以逐行推进游标。你没有这样做。

于 2009-05-03T16:54:04.777 回答
0

Oracle 和 SQL Server 之间的区别之一是后者自然地返回结果集。顺便说一句,我会使用一个函数。

在 Oracle 中,函数通常返回单个元素。光标稍后出现。

有一些在线文档可以帮助您了解 refcursor 绑定变量的使用。这是 SQL*Plus 的一个例子:

http://download.oracle.com/docs/cd/B19306_01/server.102/b14357/ch5.htm#sthref1122

我认为在 SQL Developer 中,您可以在开启自动打印的情况下做同样的事情,尽管我还没有测试过。

发现一个博客也讨论了类似的事情:

http://vadimtropashko.wordpress.com/cursors/

于 2009-05-03T17:32:33.217 回答
-1

埃塔:好的。忽略我写的。听听别人的。显然这是错误的,因为我投了反对票。

tpdi 说的是对的。声明光标后,您必须对其进行处理。

这是在嵌套循环中使用两个游标的示例

   PROCEDURE update_insert_tree (exid_in IN NUMBER, outvar_out OUT VARCHAR2)
   IS
      nxtid         NUMBER;
      phaseid       NUMBER;
      rowcounter1   NUMBER;
   BEGIN
      rowcounter1 := 0;
      outvar_out := 0;

      FOR acur IN (SELECT dept_exercise_id, phase
                     FROM ep_dept_exercise
                    WHERE exercise_id = exid_in)
      LOOP

         <<dept_loop>>
         FOR thecur IN (SELECT document_name, thelevel, sortnum, type_flag,
                               ex_save_id
                          FROM ep_exercise_save
                         WHERE exercise_id = exid_in)
         LOOP
            phaseid := acur.phase;

            IF phaseid = 0
            THEN
               phaseid := 10;

               UPDATE ep_dept_exercise
                  SET phase = 10
                WHERE dept_exercise_id = acur.dept_exercise_id;
            END IF;

            <<doc_loop>>
于 2009-05-03T17:34:26.520 回答