Вложенная ТРУБОПРОВОДНАЯ функция

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, и вам пришлось бы заменить циклы вызовом функции. с последующей итерацией по возвращенной коллекции.

Другие вопросы по тегам