【问题标题】:Merge statement array as source table合并语句数组作为源表
【发布时间】:2013-11-23 05:29:34
【问题描述】:

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

例如我有以下合并语句,编译时出现错误。 如何使用数组合并作为源表?

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

【问题讨论】:

  • 查看这篇文章以获得解决方法:PLS-00436 in 10g - Workaround
  • @PrzemyslawKruglej 非常感谢,这真的很有帮助。所以这是10g的限制吧?
  • 是的,在 11g 中,您可以访问 FORALL 语句中的各个记录字段,这与在 10g 中您会收到与您的问题相关联的错误不同。
  • @PrzemyslawKruglej 如果您作为答案发布,我将很乐意接受。

标签: sql oracle plsql merge oracle10g


【解决方案1】:

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

不过,有一些变通方法,我推荐以下文章,其中提出了一些变通方法:PLS-00436 in 10g - Workaround

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      您可以在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.
      

      【讨论】:

        猜你喜欢
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 2015-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-16
        相关资源
        最近更新 更多