Есть ли у Oracle 12 проблемы с локальными типами коллекций в SQL?

чтобы сделать длинную историю короткой, я предлагаю обсудить текст, который вы видите ниже.

при запуске:

  • компилятор Oracle 11 поднимает

    "PLS-00306: неправильный номер или типы аргументов советы в вызове "PIPE_TABLE""

    "PLS-00642: локальные типы коллекций не допускаются в инструкции SQL"

  • Oracle 12 компилирует следующий пакет без таких предупреждений, но у нас есть сюрприз во время выполнения

    при выполнении анонимного блока как есть - все в порядке (мы можем трубить некоторые строки в pipe_table функция-это не влияет)

    теперь давайте раскомментируем строку с hello; или поставить там вызов какой-либо процедуры, и снова запустить изменен anonumous блок мы получаем "ORA-22163: левая и правая боковые коллекции не одного типа"

и вопрос: У Oracle 12 разрешить локальные типы коллекций в SQL? Если да, то что не так с кодом PACKAGE buggy_report?

CREATE OR REPLACE PACKAGE buggy_report IS

  SUBTYPE t_id IS NUMBER(10);
  TYPE t_id_table IS TABLE OF t_id;

  TYPE t_info_rec IS RECORD ( first NUMBER );
  TYPE t_info_table IS TABLE OF t_info_rec;
  TYPE t_info_cur IS REF CURSOR RETURN t_info_rec;

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED;

  FUNCTION get_cursor RETURN t_info_cur;

END buggy_report;
/

CREATE OR REPLACE PACKAGE BODY buggy_report IS

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED IS
    l_table t_id_table;
    BEGIN
      l_table := p;
    END;

  FUNCTION get_cursor RETURN t_info_cur IS
    l_table  t_id_table;
    l_result t_info_cur;
    BEGIN

      OPEN l_result FOR SELECT * FROM TABLE (buggy_report.pipe_table(l_table));

      RETURN l_result;
    END;
END;
/

DECLARE
  l_cur buggy_report.t_info_cur;
  l_rec l_cur%ROWTYPE;
  PROCEDURE hello IS BEGIN NULL; END;
BEGIN

  l_cur := buggy_report.get_cursor();

  -- hello;

  LOOP
    FETCH l_cur INTO l_rec;
    EXIT WHEN l_cur%NOTFOUND;
  END LOOP;

  CLOSE l_cur;

  dbms_output.put_line('success');
END;
/

3 ответов


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

например, различные элементы, используемые в пакете buggy_report можно ORA-03113: end-of-file on communication channel при запуске скрипта (в вопросе). Это можно сделать, изменив тип t_id_table to VARRAY или TABLE .. INDEX BY ... Есть много способов и вариаций, ведущих нас к различным исключениям, которые не относятся к теме этого сообщения.

еще одна интересная вещь-это компиляция время buggy_report спецификация пакета может занять до 25 секунд, когда обычно это занимает около 0,05 секунд. Я могу определенно сказать, что это зависит от присутствия на pipe_table объявление функции, и" компиляция долгого времени " случаются в 40% случаев установки. Так что, похоже, проблема с local collection types in SQL подспудно появляются во время компиляции.

Итак, мы видим, что Oracle 12.1.0.2, очевидно, имеет ошибку в реализации использования локальных типов коллекций в язык SQL.

минимальные примеры, чтобы получить ORA-22163 и ORA-03113 следующий. Там мы предполагаем то же самое buggy_report пакета, как в вопросе.

-- produces 'ORA-03113: end-of-file on communication channel'
DECLARE   
  l_cur buggy_report.t_info_cur;

  FUNCTION get_it RETURN buggy_report.t_info_cur IS BEGIN RETURN buggy_report.get_cursor(); END;    
BEGIN
   l_cur := get_it();

   dbms_output.put_line('');
END;
/

-- produces 'ORA-22163: left hand and right hand side collections are not of same type'
DECLARE  
  l_cur buggy_report.t_info_cur;

  PROCEDURE hello IS BEGIN NULL; END;
BEGIN
  l_cur := buggy_report.get_cursor;

  -- comment `hello` and exception disappears
  hello;

  CLOSE l_cur;
END;
/

да, в Oracle 12c вам разрешено использовать локальные типы коллекций в SQL.

документация База Данных Новые Функции Руководство говорит:

PL / SQL-конкретные типы данных, разрешенные через интерфейс PL/SQL-to-SQL

оператор таблицы теперь может использоваться в программе PL/SQL для коллекции, тип данных которой объявлен в PL/SQL. Это также позволяет типу данных быть ассоциативным массивом PL/SQL. (В предыдущих выпусках тип данных коллекции должен быть объявлен на уровне схемы.)

однако я не знаю, почему ваш код не работает, возможно, эта новая функция все еще имеет ошибку.


я повозился с вашим примером. Трюк, как Oracle 12c может использовать коллекции PL/SQL в операторах SQL, заключается в том, что Oracle создает типы объектов суррогатной схемы с совместимыми атрибутами типа SQL и использует эти суррогатные типы в запросе. Твое дело похоже на жука. Я проследил выполнение, и суррогатные типы создаются только один раз, если они не существуют. Таким образом, эффективный тип не изменяется и не перекомпилируется (не знаю, выполняется ли неявная перекомпиляция с помощью инструкции ALTER) во время выполнения конвейерная функция. И проблема возникает, только если вы используете на