Разница между параметром CURSOR «IN» и «IN OUT» в Oracle - PullRequest
1 голос
/ 21 августа 2010

С Oracle : «Когда вы объявляете переменную курсора в качестве формального параметра подпрограммы, которая выбирается из переменной курсора, вы должны указать режим IN или IN OUT. Если подпрограмма также открывает переменную курсора, вы должны указать режим IN OUT".

Но я могу закодировать это (только параметр OUT):

create or replace procedure mycur_out(mc OUT mycurpkg.mytypecur)  as 
begin
    open mc for select * from mytable; 
end mycur_out;

и работает равным (параметр IN OUT)

create or replace procedure mycur_inout(mc IN OUT mycurpkg.mytypecur) 
as
begin
    open mc for select * from table10;
end mycur_inout;

Кроме того, с динамическим курсором тоже все в порядке:

create or replace procedure mycur_out_ref(mc out mycurpkg.mytyperefcur) 
as
begin
    open mc for 'select * from table10';
end mycur_out_ref;

Я проверил 3 случая непосредственно из оракула и из VB6 с ADO, и никаких проблем. Итак, есть ли в этом случае разница между IN , использующими только параметры курсоров "OUT" и "IN OUT"?

UPDATE Причина, по которой я спрашиваю:

  • Мы читаем данные, используя процедуры, аналогичные к примерам (просто откройте курсоры). Параметры курсора всегда "IN OUT" (не спрашивайте меня почему, я пытаюсь выяснить)
  • Процедуры вызываются с помощью ADO / VB6
  • Теперь мы пытаемся использовать некоторые подпрограммы из JDBC, но адаптер, видимо, просто принимает OUT Параметры в этом случае.
  • Наконец, основная причина, я хочу изменить параметры курсора на БД подпрограммы только OUT, но сначала я хочу знать эффекты залога этого изменения.

Спасибо!

Ответы [ 2 ]

1 голос
/ 23 августа 2010

В тексте, который вы цитируете из руководства, обратите внимание, что в нем конкретно говорится о «подпрограмме , извлекаемой из переменной курсора ».Ни один из ваших примеров не делает этого, поэтому цитата к ним не относится.

Однако, тем не менее, кажется, что нет ничего плохого в использовании OUT только в такой ситуации, если подпрограмма и открывается, и выбираетпеременная курсора:

SQL> variable c refcursor

SQL> set serveroutput on
SQL> create or replace procedure no_good (c  OUT sys_refcursor)
  2     as
  3        my_dummy  dual.dummy%type;
  4     begin
  5       open c for select dummy from dual union all select dummy from dual;
  6       fetch  c into my_dummy;
  7       dbms_output.put_line( my_dummy );
  8     end;
  9  /

Procedure created.

SQL> exec no_good( :c )
X

PL/SQL procedure successfully completed.

SQL> print c

D
-
X

Я думаю, что текст на самом деле пытается сделать две точки, которые несколько независимы друг от друга.Во-первых, если вы хотите передать какую-либо уже открытую переменную курсора в подпрограмму, которая будет извлекать ее, параметр должен быть объявлен IN или IN OUT.Во-вторых, если вы хотите передать переменную курсора в подпрограмму, которая затем откроет ее, параметр должен быть объявлен OUT или IN OUT.Это верно независимо от того, действительно ли вы заботитесь о передаче значения переменной курсора обратно вызывающей стороне:

SQL> create or replace procedure no_good (c  IN sys_refcursor)
  2     as
  3        my_dummy  dual.dummy%type;
  4     begin
  5       open c for select dummy from dual;
  6       fetch  c into my_dummy;
  7       dbms_output.put_line( my_dummy );
  8       close c;
  9     end;
 10  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE NO_GOOD:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/6      PL/SQL: SQL Statement ignored
5/11     PLS-00361: IN cursor 'C' cannot be OPEN'ed

Эта ошибка может быть исправлена ​​путем изменения режима параметра, но на самом деле это может привести ксмысл просто сделать переменную курсора локальной переменной, а не параметром.

0 голосов
/ 21 августа 2010

Если я правильно понял вопрос, разница в том, что с версией IN OUT вы можете передать курсор извне процедуры, а затем изменить эту переменную (аналогично разнице между OUT и IN OUT для простой числовой переменной).

Курсор параметра OUT начинается как значение NULL / закрытый курсор.

Версия параметра IN OUT начинается с любого состояния, переданного извне.

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

Еще одна вещь, которую подход IN OUT допускает, а не подход OUT - это выполнение действий на основе переданного курсора и изменение возвращаемого курсора.

PROCEDURE lp_test2 (mc IN OUT mycurpkg.mytypecur)
IS
  lr table10%ROWTYPE;
BEGIN 
   IF mc%ISOPEN THEN 
      FETCH mc INTO lr;
      IF mc%NOTFOUND THEN
         CLOSE mc;
         /* Switch cursor to alternative table */
         open mc for select * from schema2.table10;
      END IF;
   END IF;
END lp_test2;

Мне просто трудно думатьреальной ситуации, где вы можете захотеть (возьмите переменную курсора, приведите его обратно, яв оператор SQL, добавить дополнительный динамический SQL и вернуть весь лот обратно как тот же курсор ??).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...