Skip to Main Content
  • Questions
  • Using PL/SQL collection in DML statements

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Andrzej.

Asked: January 10, 2017 - 10:30 am UTC

Last updated: July 07, 2021 - 2:38 am UTC

Version: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

Viewed 10K+ times! This question is

You Asked

Hi Tom!

I encountered a problem using PL/SQL collections in DML statements inside stored procedure, please find complete test case in provided LiveSQL.

In the test package there are two, very similar procedures, which firstly collect some IDs into associative array and then use this array in sub-select of other SQL statements:
- TEST_OK procedure performs SELECT statements - works fine
- TEST_NOK procedure which tries to do a DELETE: DELETE FROM ali_test_tab WHERE ID IN (SELECT COLUMN_VALUE FROM TABLE(t2)) fails with runtime error ORA-00902.

I use exactly the same sub-select in both procedures, so I don't understand why it doesn't work in DELETE (in UPDATE it fails as well). I already tried to explicitly convert datatypes - but it didn't help.

I found a workaround - define type on schema level, not on package level - but I prefer to keep everything within this package, so I would like to kindly ask you for help. Perhaps I overlook some obvious issue, but I can't understand why this works for SELECT but not for DELETE/UPDATE.

Thank you in advance for any help!

Best regards,
Andrzej

with LiveSQL Test Case:

and Chris said...

You can't use the table() operator on PL/SQL data types in insert, update, delete or merge:

create table t (
  x int
);

insert into t 
  select rownum from dual connect by level <= 5;
commit;

create or replace package pkg as
  type tp is table of number index by pls_integer;
end pkg;
/

declare
  arr pkg.tp;
begin
  arr(1) := 1;
  arr(3) := 2;
  arr(2) := 3;
  delete t
  where  x in (select column_value from table(arr));
end;
/

ORA-00902: invalid datatype
ORA-06512: at line 7
00902. 00000 -  "invalid datatype"


Sadly this isn't listed in the known restrictions about this. We've filed a doc bug to update this.

If you want to do this you need to use a SQL type:

create or replace type tp is table of number;
/

declare
  arr tp := tp(1, 2, 3);
begin
  delete t
  where  x in (select column_value from table(arr));
end;
/

PL/SQL procedure successfully completed.

select * from t;

X  
4  
5  



Rating

  (2 ratings)

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

Comments

Doc bug which I expected :)

Andrzej Lisowski, January 10, 2017 - 4:04 pm UTC

Thank you very much for such a quick answer! To be honest - I expected that this is a kind of bug.

But technically speaking - why does it work with schema level type but not with package level type? Is there any technical reason behind that?

Best regards,
Andrzej
Chris Saxon
January 10, 2017 - 5:17 pm UTC

You can only use the table() operator on PL/SQL associative arrays in 12c. The "technical reason" is because DML support isn't implemented yet!

Error can and should be evaluated during compile time

CChristian Massnick, July 06, 2021 - 8:52 am UTC

I have no problem that this feature is not implemented (yet).
But this constellation can be evaluated during compile time and shoul lead to a compile time error. This would avoid debugging mysterious runtime errors later.
Connor McDonald
July 07, 2021 - 2:38 am UTC

Agreed. But we are where we are.

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