Merge statement array as source table Merge statement array as source table oracle oracle

Merge statement array as source table


There is a restriction in Oracle 10g - you can't access individual fields of records in FORALL statement. You could do it if you were using Oracle 11g.

There are workarounds, however, and I recommend the following article that proposes a few of them: PLS-00436 in 10g - Workaround.


The problem here is that you are referring to the same collection in your SET clause and WHERE clause. See Oracle Documentation for Forall statement, go to the Restrictions section, second bullet point.

I would suggest you rename your varray collection as something different, as it is a keyword. I would also suggest you separate this collection into multiple scalar collections (varrays or nested tables having only one column) for each column and then use these collections in your forall statement.


You can generate the source dataset in the MERGE clause by selecting it from DUAL:

SQL> set serveroutput onSQL> create table projects (  2     proj_id integer not null primary key,  3     proj_title varchar2(20)  4  );Table created.SQL> insert into projects (proj_id, proj_title) values (1, 'Project One');1 row created.SQL> insert into projects (proj_id, proj_title) values (2, 'Project Two');1 row created.SQL> commit;Commit complete.SQL> select *  2    from projects;   PROJ_ID PROJ_TITLE---------- --------------------         1 Project One         2 Project Two2 rows selected.SQL> declare  2     type varray_t is varray(2) of projects%rowtype;  3     arr varray_t;  4  begin  5     with test_data as (select 2 as proj_id, 'New Project Two' as proj_title from dual  6                        union all select 3 as proj_id, 'New Project Three' as proj_title from dual)  7     select proj_id, proj_title  8       bulk collect into arr  9       from test_data; 10 11     forall i in arr.first .. arr.last 12        merge into projects 13        using (select arr(i).proj_id as proj_id, 14                      arr(i).proj_title as proj_title 15                 from dual) mrg 16           on (projects.proj_id = mrg.proj_id) 17         when matched then update set projects.proj_title = mrg.proj_title 18         when not matched then insert (proj_id, proj_title) values (mrg.proj_id, mrg.proj_title); 19 20     dbms_output.put_line(sql%rowcount || ' rows merged'); 21 22     commit; 23  end; 24  /2 rows mergedPL/SQL procedure successfully completed.SQL> select *  2    from projects;   PROJ_ID PROJ_TITLE---------- --------------------         1 Project One         2 New Project Two         3 New Project Three3 rows selected.