Вложенная ТРУБОПРОВОДНАЯ функция
create type data_type_1 as object (x number, y number)
/
create type table_type_1 as table of data_type_1
/
create or replace package xyz AS
function main_xyz return table_type_1 pipelined;
function sub_func return table_type_1 pipelined;
function sub_func1 return table_type_1 pipelined;
end xyz;
/
create package body XYZ AS
function main_xyz return data_type_1 pipelined is
begin
--code
--pipe row(sub_func); --edit_1
FOR rec in (select * from table(sub_func1(x,y))) LOOP
pipe row(rec);
END LOOP;
end;
--function sub_func return data_type_1 pipelined is --edit_1
--begin --edit_1
--code --edit_1
--pipe row(def); --def is data_type_1 --edit_1
--end; --edit_1
function sub_func_1(x in number, y in number) return data_type_1 pipelined is
begin
--code
loop
pipe row(abc); --abc is data_type_1
end loop;
end;
end;
create package body ABC AS
function main_ABC is
begin
--code
FOR rec in (select * from table(main_xyz)) LOOP
pipe row(rec);
END LOOP;
end;
end;
Ошибка, которую я получаю...
Ошибка отображается в блоке main_xyz, где вызывается sub_func1.
[Ошибка] PLS-00382 (): PLS-00382: выражение имеет неправильный тип
[Ошибка] PLS-00306 (): PLS-00306: неверный номер или типы аргументов при вызове
[Ошибка] ORA-00904 (): PL/SQL: ORA-00904:: неверный идентификатор
[Ошибка] PLS-00364 (): PLS-00364: использование переменной индекса цикла "REC" недопустимо
Что не так в приведенном выше коде? и почему?
1 ответ
Ваши функции возвращаются data_type_1
и коллекция таблиц тоже пытается это использовать. Но обоим нужен тип коллекции, даже если вы ожидаете, что они будут возвращать только одно значение (в этом случае нет особой конвейерной обработки). Вы не можете передать тип коллекции напрямую, вы передаете элемент коллекции по конвейеру. Так data_type_1
должен быть скалярным или объектным / типом записи, и вам нужен другой тип, который является коллекцией из них.
create type data_type_1 as object (x number, y number)
/
create type table_type_1 as table of data_type_1
/
create or replace package xyz AS
function main_xyz return table_type_1 pipelined;
function sub_func return table_type_1 pipelined;
function sub_func1 return table_type_1 pipelined;
end xyz;
/
create or replace package body xyz as
function main_xyz return table_type_1 pipelined is
begin
--code
for rec in (select * from table(sub_func)) loop
pipe row(data_type_1(rec.x, rec.y));
end loop;
for rec in (select * from table(sub_func1)) loop
pipe row(data_type_1(rec.x, rec.y));
end loop;
end;
function sub_func return table_type_1 pipelined is
def data_type_1;
begin
--code
pipe row(def); --def is data_type_1
end sub_func;
function sub_func1 return table_type_1 pipelined is
abc data_type_1;
begin
--code
loop
pipe row (abc); --abc is data_type_1
end loop;
end sub_func1;
end xyz;
/
Итак, я добавил тип таблицы вашего существующего data_type_1
и изменил определения функций, чтобы они возвращали этот тип таблицы. pipe row
все еще использует data_type_1
- каждая строка в типе таблицы. Вашему циклу нужен запрос для его курсора, а не прямой вызов table()
Я тоже это изменил. И pipe row(sub_func);
также должен быть похожий цикл над запросом.
Вы пометили это только как PL/SQL, но потому, что можете main_xyz
из простого SQL, и потому что вы вызываете подфункции из контекста SQL в этих циклах, data_type_1
а также table_type_1
нужно создавать на уровне схемы, а не в PL/SQL. (Это немного изменилось в 12c, но недостаточно, чтобы помочь здесь).
Если вы хотите, чтобы они были в виде PL/SQL-типов, объявленных в спецификации пакета, то вы не могли бы вызвать функцию из контекста не-PL/SQL, и вам пришлось бы заменить циклы вызовом функции. с последующей итерацией по возвращенной коллекции.