как работают хранимые процедуры оракула (с курсорами)? - PullRequest
1 голос
/ 03 мая 2009

У меня есть следующая хранимая процедура оракула

    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 ]

5 голосов
/ 04 мая 2009

Хранимая процедура возвращает что-то, просто вы ничего не делаете с результатами.

Вы можете сделать это, просто запустив следующий скрипт в 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;
1 голос
/ 03 мая 2009

Вы открыли курсор. Вы ничего не выбрали из него, не обновили или не продвинули.

Все открытые, фактически, выбирают совпадающие строки во временной памяти, так что вы можете перемещать курсор за строкой. Что вы не сделали.

0 голосов
/ 03 мая 2009

ETA: ОК. Не обращайте внимания на то, что я написал. Слушай кого-то еще. Видимо, это неправильно, так как я проголосовал.

То, что сказал ТПДИ, верно. Вы должны сделать что-то с курсором после того, как объявите это.

Вот пример использования двух курсоров во вложенных циклах

   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>>
0 голосов
/ 03 мая 2009

Одним из отличий между 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/

...