Таблица NESTED в подзапросе DML - PullRequest
1 голос
/ 28 апреля 2020

Используя Oracle 12 c EE, как я могу использовать типы пакетов PL / SQL в подзапросах DML, не вызывая исключения "ORA-00902: неверный тип данных"?

Пример схемы

--PL/SQL package types.
create or replace package test_pkg as
    TYPE type_record IS RECORD(
        column1        NUMBER,
        column2        NUMBER,
        column3        NUMBER);

    TYPE type_table IS TABLE OF type_record;
end;
/

--For comparison, the same types but as SQL objects.
CREATE OR REPLACE TYPE type_record IS OBJECT(
    column1        NUMBER,
    column2        NUMBER,
    column3        NUMBER);

CREATE OR REPLACE TYPE type_table IS TABLE OF type_record;

--Table for testing DML.
create table tableX(a number);

PL / SQL Типы в SQL SELECT - РАБОТАЕТ

Преобразование из типов PL / SQL в SQL отлично работает для SELECTS. Приведенный ниже код работает нормально:

declare
    vt test_pkg.type_table;
    v_count number;
begin
    select count(*)
    into v_count
    from dual
    where not exists(select column1 from table(vt));
end;
/

PL / SQL Типы в SQL UPDATE - FAILS

Но использование тех же типов и подзапросов в выражении DML вызывает исключение: " ORA-00902: недопустимый тип данных / ORA-06512: в строке 4 ".

declare
    vt test_pkg.type_table;
begin
    update tableX set a = 1
    where not exists (select column1 from table(vt));
end;
/

SQL Типы в SQL ОБНОВЛЕНИЕ - РАБОТАЕТ

Для сравнения используется SQL объекты в подзапросах прекрасно работает в DML:

declare
    vt type_table;
begin
    update tableX set a = 1
    where not exists (select column1 from table(vt));
end;
/

Создание SQL объектов для каждого запроса - это обходной путь, но это создаст много ненужных объектов схемы. Есть ли способ заставить типы пакетов PL / SQL работать в подзапросах DML?

1 Ответ

0 голосов
/ 01 мая 2020

Я полагаю, что это вопрос мнения, так как я использую типы уровня db, потому что (imho) именно это и делает код чистым. Но это просто другой взгляд на это. Однако то, что вы ищете, по крайней мере, в этом случае, не так сложно. Вы уже создаете пакет, который использует эти определения. Вы можете просто переместить определения в пакет spe c. Тогда будут небольшие или никакие изменения кода, необходимые. Также эти определения могут все еще использоваться вне самого пакета.

create or replace package pkg_t1 as  
   type type_record is record(
      column1        number,
      column2        number,
      column3        number);

   type type_table is table of type_record;

   function build_type_records(rows_to_build in integer) 
     return type_table;

   function build_pipe_records(rows_to_build in integer) 
     return type_table 
     pipelined;    

end pkg_t1;
/

create or replace package body pkg_t1 as

   function build_type_records(rows_to_build in integer) 
   return  type_table 
   is  
      v_type type_table := type_table();
   begin 
      for i in 1 .. rows_to_build 
      loop 
         v_type.extend;      
         v_type(i).column1 := trunc(dbms_random.value(1,100)); 
         v_type(i).column2 := trunc(dbms_random.value(100,500));
         v_type(i).column3 := dbms_random.value();
      end loop ;

     return  v_type;
   end build_type_records; 

  function build_pipe_records(rows_to_build in integer) 
    return type_table 
    pipelined 
  is
    v_rec type_table;
  begin
    v_rec:= build_type_records(rows_to_build); 
    for i in 1 .. v_rec.count
    loop
      pipe row (v_rec(i));
    end loop; 
  end build_pipe_records;

end pkg_t1;
/ 

declare 
  tt pkg_t1.type_table; 
  num_of_rows integer := &Number_of_rows;
begin
  tt := pkg_t1.build_type_records( num_of_rows );
  for i in 1 .. tt.count
  loop
      dbms_output.put_line( 'Result: '
                            || 'Column1==>' || tt(i).column1 || ', ' 
                            || 'Column2==>' || tt(i).column2 || ', '
                            || 'Column3==>' || tt(i).column3
                          ) ; 
  end loop; 
end ; 
/

select * from table(pkg_t1.build_pipe_records(&Rows_Desirded));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...