将语句数组合并为源表

时间:2013-11-11 12:03:50

标签: sql oracle plsql merge oracle10g

是否可以将数组用作合并语句的源

E.g。我有下面的合并语句,当我编译时,我收到错误。 如何使用merge with array作为源表?

PLS-00436: implementation restriction: cannot reference fields of BULK In-BIND 
table of records 

程序代码

CREATE or REPLACE PROCEDURE my_proc (varray IN my_array)
     AS
     BEGIN
          FORALL i IN varray.first..varray.last
          MERGE INTO tab t
          USING dual
          ON ( t.proj_id = varray(i).proj_id)
          WHEN MATCHED THEN
          UPDATE  set
          proj_title = varray (i).proj_title
                      WHERE   proj_id = varray (i).proj_id
            WHEN NOT MATCHED THEN
            insert (proj_id,proj_title)
            values (varray (i).proj_id,varray (i).proj_title);
         values (varray (i).proj_id,varray (i).proj_title);

3 个答案:

答案 0 :(得分:5)

Oracle 10g中存在限制 - 您无法在FORALL语句中访问单个记录字段。如果您使用的是Oracle 11g,则可以这样做。

但是,有一些解决方法,我推荐以下文章提出其中一些:PLS-00436 in 10g - Workaround

答案 1 :(得分:2)

这里的问题是您在SET子句和WHERE子句中引用了相同的集合。请参阅Oracle Documentation for Forall statement,转到限制部分,第二个项目符号点。

我建议您将varray集合重命名为不同的内容,因为它是关键字。我还建议你将这个集合分成多个标量集合(varrays或只有一列的嵌套表),然后在你的forall语句中使用这些集合。

答案 2 :(得分:2)

您可以从MERGE中选择DUAL子句中的源数据集:

SQL> set serveroutput on
SQL> 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 Two

2 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 merged

PL/SQL procedure successfully completed.

SQL> select *
  2    from projects;

   PROJ_ID PROJ_TITLE
---------- --------------------
         1 Project One
         2 New Project Two
         3 New Project Three

3 rows selected.