Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Cursor variable "портится" при возврате хранимкой.  [new]
RUS 21
Member

Откуда:
Сообщений: 45
Хранимка (на закомментированное не обращайте внимание.об этом ниже):
+
CREATE OR REPLACE PROCEDURE test_rc(
    p_rc IN OUT sys_refcursor)
IS
--str varchar2(100) := 'SELECT 1 FROM user_objects where rownum<2';
k number;
BEGIN
  DBMS_OUTPUT.put_line('Зашли в test_rc');
  execute immediate 'begin OPEN :p_rc FOR SELECT 666 FROM user_objects where rownum<2; end;' USING  IN OUT p_rc;
  /* Внутри хранимки курсор "живой"
    loop 
    fetch p_rc into k;
    DBMS_OUTPUT.put_line('Изнутри:'||k);
    exit when p_rc%NOTFOUND;
  end loop;
  */
  --OPEN p_rc FOR select 2 from user_objects where rownum<2;
  --CLOSE p_rc;
  --OPEN p_rc FOR select 3 from user_objects where rownum<2;
  --OPEN p_rc FOR select 4 from user_objects where rownum<2;
  if p_rc%ISOPEN then 
    DBMS_OUTPUT.put_line('p_rc внутри хранимки открыт!');
  else
    DBMS_OUTPUT.put_line('p_rc внутри хранимки НЕ открыт!');
  end if;
  DBMS_OUTPUT.put_line('Вышли из test_rc');
  
END;

Тест:
+
set serveroutput on
declare 
rc sys_refcursor;
i number;
begin
  if rc%ISOPEN then 
    DBMS_OUTPUT.put_line('До запуска хранимки: rc снаружи хранимки открыт!');
  else
    DBMS_OUTPUT.put_line('До запуска хранимки: rc снаружи хранимки НЕ открыт!');
  end if;
  test_rc(rc);
  if rc%ISOPEN then 
    DBMS_OUTPUT.put_line('После запуска хранимки: rc снаружи хранимки открыт!');
  else
    DBMS_OUTPUT.put_line('После запуска хранимки: rc снаружи хранимки НЕ открыт!');
  end if;
  loop 
    fetch rc into i;
    DBMS_OUTPUT.put_line('Снаружи:'||i);
    exit when rc%NOTFOUND;
  end loop;
end;

Пример сильно упрощен, поэтому в необходимости использовать in out sys_refcursor и dynamic SQL поверьте на слово.
Проблема в том, что внутри процедуры курсор полноценный (для проверки нужно раскомментировать в хранимке код между /* ... */). А в анонимном блоке, вызвавшем её (либо в процедуре уровнем выше) он вроде бы как открыт(см. rc%ISOPEN), но бесполезен.
Главный вопрос: что такого происходит в динамике, что в том же блоке курсор полноценный, а во внешнем блоке уже нет? Или я допустил где-то ошибку?

Ну и тут же были проведены другие тесты.
Например, если не использовать "динамику". Курсор был открыт в статике, тогда даже если:
  • 1)его потом закрыть и открыть заново (select 2 и select 3),
  • 2)не закрывая, открыть снова для другой выборки (select 4),
    то курсор снаружи рабочий.
    Но если перед этим курсор открывался в динамике, то ни последующее закрытие, ни открытие его же в статике уже не позволяет делать выборку во внешнем блоке.

    Гугл прочесал.
  • 29 сен 11, 17:58    [11357487]     Ответить | Цитировать Сообщить модератору
     Re: Cursor variable "портится" при возврате хранимкой.  [new]
    andrey_anonymous
    Member

    Откуда: Москва
    Сообщений: 18398
    CREATE OR REPLACE PROCEDURE test_rc(
        p_rc IN OUT NOCOPY sys_refcursor)
    IS
    l_rc sys_refcursor;
    k number;
    BEGIN
      DBMS_OUTPUT.put_line('Зашли в test_rc');
      execute immediate 'begin OPEN :XXX FOR SELECT 666 FROM user_objects where rownum<2; end;' USING IN OUT l_rc;
      p_rc := l_rc;
      if p_rc%ISOPEN then 
        DBMS_OUTPUT.put_line('p_rc внутри хранимки открыт!');
      else
        DBMS_OUTPUT.put_line('p_rc внутри хранимки НЕ открыт!');
      end if;
      DBMS_OUTPUT.put_line('Вышли из test_rc');
    RETURN;  
    END;
    /
    
    29 сен 11, 18:13    [11357613]     Ответить | Цитировать Сообщить модератору
     Re: Cursor variable "портится" при возврате хранимкой.  [new]
    RUS 21
    Member

    Откуда:
    Сообщений: 45
    andrey_anonymous,
    Это понятно.. Так в итоге и юзаем. Но вопрос: что не так в таком использовании?
    29 сен 11, 18:28    [11357704]     Ответить | Цитировать Сообщить модератору
     Re: Cursor variable "портится" при возврате хранимкой.  [new]
    andrey_anonymous
    Member

    Откуда: Москва
    Сообщений: 18398
    Баг на баге сидит и багами погоняет :)

    ... давнооо здесь сидим:
    Не закрывается sys_refcursor
    29 сен 11, 22:46    [11358655]     Ответить | Цитировать Сообщить модератору
     Re: Cursor variable "портится" при возврате хранимкой.  [new]
    RUS 21
    Member

    Откуда:
    Сообщений: 45
    andrey_anonymous,

    Спасибо. Так и знал, что на родном sql.ru должен был быть уже ответ..пардон за невнимательность.
    Открытие курсора в статике перед динамиком или промежуточный курсор - Oracle милосерден. Целых 2 варианта обхода бага))
    30 сен 11, 08:25    [11359428]     Ответить | Цитировать Сообщить модератору
    Все форумы / Oracle Ответить