Есть ли у 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) во время выполнения конвейерная функция. И проблема возникает, только если вы используете на