4

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

例如,我有下面的合并语句,当我编译时,我得到了错误。如何使用与数组合并作为源表?

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);
4

3 回答 3

5

Oracle 10g 中有一个限制——您不能访问FORALL语句中记录的各个字段。如果您使用的是 Oracle 11g,您可以做到这一点。

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

于 2013-11-11T13:08:55.140 回答
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.
于 2013-11-11T12:54:41.420 回答
2

这里的问题是您在SET子句和WHERE子句中指的是同一个集合。有关Forall 语句,请参阅Oracle 文档,转到限制部分,第二个要点。

我建议您将您的varray收藏重命名为不同的名称,因为它是一个关键字。我还建议您将此集合分成多个标量集合(仅包含一列的变量或嵌套表),然后在您的 forall 语句中使用这些集合。

于 2013-11-11T12:34:23.693 回答