Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question.

Asked: August 31, 2017 - 4:35 pm UTC

Last updated: February 06, 2023 - 3:56 am UTC

Version: PL/SQL Release 12.1.0.2.0 - Production

Viewed 1000+ times

You Asked

Hello AskTom Team,

I am using TABLE operator on locally defined nested table type.

As per my understanding of 12c plsql manual, it is supported

I am doing following:
- Defined a type in package specification "type t1_tblType is TABLE of r1_recType;"
- In procedure of the package body, I populate a nested table variable (t1_tbl) of same type and then try to use that in following manner
---- Using cursor for loop , where I am selecting from this nested table variable using table operator, it is working fine and printing its content
---- When I used same nested variable in "insert into....select from TABLE(nested table variable)" , it does not work. I have tried 2-3 variations of insert statement - for all of them, it returns - "ORA-00902: invalid datatype"

Following are variation I have tried
insert into t3 select * from TABLE(t1_tbl);
insert into t3 select id1,a1 from TABLE(t1_tbl);
insert into t3 (id1,a1) select id1,a1 from TABLE(t1_tbl);


So, it seems you can select from nested table using TABLE operator. But, in INSERT - it does not seem to be supported.


Please let me know if my understanding is correct or please suggest, if there is any mistake I am making and how to correct it (I understand, I cna use forall statement...but is there any other way, especially as I have mentioned above using TABLE operator)


I am attaching entire code snippet below (DDL statement for table t3 is listed in commented form at beginning, please run it separately, in case you want to try it at your end)

/*
create table t3
(
id1 number(18),
a1 varchar2(30)
);
*/
create or replace package test_pkg02
as

type r1_recType is RECORD 
(
id1 number(18),
a1 varchar2(30)
);

type t1_tblType is TABLE of r1_recType;-- INDEX BY PLS_INTEGER;


procedure p1;


end test_pkg02;
/
show errors;


create or replace package body test_pkg02
as


procedure p1 is
 
 r1_rec r1_recType;
 t1_tbl t1_tblType;
 
 i pls_integer;

begin

   t1_tbl := t1_tblType();

   
  r1_rec.id1 := 101;
  r1_rec.a1 := 'a101';
   
   t1_tbl.EXTEND;  
    t1_tbl(1) := r1_rec;  

  r1_rec.id1 := 102;
  r1_rec.a1 := 'a102';
  
     t1_tbl.EXTEND;
  t1_tbl(2) := r1_rec;
 
  r1_rec.id1 := 103;
  r1_rec.a1 := 'a103';
  
     t1_tbl.EXTEND;
  t1_tbl(3) := r1_rec;
 
  for cur_rec in ( select *  from  TABLE(t1_tbl) b )
  loop
    dbms_output.put_line('cur_rec.id1='|| cur_rec.id1);
  end loop;

  
  insert into t3 select * from TABLE(t1_tbl);
  --insert into t3  select id1,a1 from TABLE(t1_tbl);
   -- insert into t3 (id1,a1) select id1,a1 from TABLE(t1_tbl);



end p1;


end test_pkg02;
/
show errors;




set serveroutput on size 100000;
execute test_pkg02.p1;










and Connor said...

Thanks for the test case.

That is actually a *known* restriction. See slide 24 in the following presentation from the 12c release

http://www.oracle.com/technetwork/database/features/plsql/new-plsql-in-12c-2372822.pdf

But sadly that info was missed from the documentation. Bug 22378398 is for correcting the documentation.

You'll need to workaround using SQL types, ie, create or replace type ...

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Table operator on Associative Arrays

Rajeshwaran, Jeyabal, January 31, 2023 - 10:54 am UTC

Team,

the below test case is from 21c(21.3) it seems, TABLE operator on Associative Arrays were not working in the subquery clause.

Is this an expected behavior or i am hitting a bug here.
demo@PDB1> variable n refcursor
demo@PDB1> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     open :n for select * from table(l_data) ;
  5  end;
  6  /

PL/SQL procedure successfully completed.

demo@PDB1> print n

COLUMN_VALUE
-------------
AB
CD
EF

demo@PDB1> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     update emp
  5     set ename ='X'
  6     where ename in ( select * from table(l_data) );
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-00902: invalid datatype
ORA-06512: at line 4


demo@PDB1> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     update emp
  5     set ename ='X'
  6     where ename in ( 'AB','CD','EF' );
  7  end;
  8  /

PL/SQL procedure successfully completed.

demo@PDB1>


Connor McDonald
February 06, 2023 - 3:56 am UTC

I don't think its a subquery issue but DML versus SELECT


SQL> variable n refcursor
SQL> declare
  2         l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3      begin
  4         open :n for select * from table(l_data) ;
  5      end;
  6      /

PL/SQL procedure successfully completed.

SQL>
SQL> declare
  2         l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3      begin
  4         update emp
  5         set ename ='X'
  6         where ename in ( select * from table(l_data) );
  7      end;
  8  /
declare
*
ERROR at line 1:
ORA-00902: invalid datatype
ORA-06512: at line 4


SQL>
SQL>
SQL> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     for i in (
  5        select *
  6        from emp
  7        where ename in ( select * from table(l_data) )
  8     )
  9     loop
 10       null;
 11     end loop;
 12  end;
 13  /

PL/SQL procedure successfully completed.

SQL>
SQL> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     delete
  5        from emp
  6        where ename in ( select * from table(l_data) );
  7  end;
  8  /
declare
*
ERROR at line 1:
ORA-00902: invalid datatype
ORA-06512: at line 4


SQL>
SQL> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     insert into emp ( ename )
  5     select ename
  6     from emp
  7     where ename in ( select * from table(l_data) );
  8  end;
  9  /
declare
*
ERROR at line 1:
ORA-00902: invalid datatype
ORA-06512: at line 4


SQL>
SQL> declare
  2     l_data dbms_sql.varchar2_table := dbms_sql.varchar2_table('AB','CD','EF');
  3  begin
  4     insert into emp ( ename )
  5     select * from table(l_data);
  6  end;
  7  /
declare
*
ERROR at line 1:
ORA-00902: invalid datatype
ORA-06512: at line 4


SQL>


not sure if that's a documented restriction or not - will dig around

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library