Oracle 11g - 如何在merge语句中执行多行?

时间:2015-09-21 02:26:34

标签: oracle oracle11g merge row procedure

我现在正在使用merge into语句,但它不符合要求。目前的代码如......

create or replace procedure 
  mv_data
is 
begin
  merge into WORK w
    using (select * from IF_WORK where batch = 0) i
      on (w.token in (select token from IF_WORK where batch = 0))
    when matched then
      update set 
        w.area = i.area
        , w.cust_id = i.cust_id
        , w.status = i.status
        , w.changed = sysdate
      where w.token = i.token
      -- I want to put "update IF_WORK set batch = 1 where work_id = i.work_id" here. Exception handling also.
    when not matched then      
      insert 
        (
        token, area, cust_id, status)
      values
        (i.token, i.area, i.cust_id, i.status)
      -- I want to put "update IF_WORK set batch = 1 where work_id = i.work_id" here. Exception handling also.
      ; 

  update IF_WORK set batch = 1;      
  commit;

  exception 
    when others then rollback;  
end;

以下是我所关注的......

  1. 在当前代码中,它运行for循环而不是全部更新。需要个人控制。 (我必须仅为成功数据更新IF_WORK表)
  2. exception声明的位置。我想为每一行回滚或提交,而不是为所有行。但是,现在它将全部回滚。
  3. 所以我尝试将代码更改为一个merge过程和处理单行的过程。但我知道不能在when matched then使用程序。

    我该如何实现?有什么好的陈述/方法吗? 感谢。

    P.S由于我使用Java这么长时间,我提供的代码看起来像Java中的跟随。

    /* This is something I wanted
        public static void main(String[] args) {
            List<String> aList = new ArrayList<String>();
            for(String s : aList){
                try{
                    * INSERT data !!! *
                }catch(Exception e) {
                    * UPDATE data !!! *
                }
            }
        }
        */
    
        // Something I implemented for now
        public static void main(String[] args) {
            List<String> aList = new ArrayList<String>();
            try{
                for(String s : aList){
                    * INSERT data !!! *
                }
            }catch(Exception e) {
                * UPDATE all !!! *
            }
        }
    

2 个答案:

答案 0 :(得分:0)

由于尚未回答,我想我会部分回答。

要完全回答它并不容易,因为我不知道数据库设计的所有细节。

但是,通常,您可以使用Oracle Implicit游标来开始循环遍历一组数据。

您仍然可以使用Merge语句,现在插入或更新,只处理一行。

下面是一些伪代码:

create or replace procedure 
  mv_data
is 
begin

FOR ifwork IN (
  SELECT area, 
      cust_id, 
      status, 
      token,
      work_id,
      whatever_your_primary_key_column_is
  FROM IF_WORK
  WHERE batch=0
)
LOOP
merge into WORK w
  using (select ifwork.area, ifwork.cust_id, ifwork.status, ifwork.token, ifwork.work_id from dual) i
  ...////rest of your MERGE statement here

//update if_work set batch = 1 where whatever_your_primary_key_column_is=ifwork.whatever_your_primary_key_column_is
    END LOOP;



END;

答案 1 :(得分:0)

这就是我用罗伯特的答案解决这个问题的方法。

我做了2个程序(那些没有exception语句。在调用程序中处理那些程序)

  1. 插入原始表格和其他
  2. 更新原始表格和其他
  3. 比我在loop声明

    中调用它
    create or replace procedure 
      mv_data
    is 
    begin
      for if_row in (
        select 
          *
        from IF_WORK
        where batch = 0
      )
      loop 
        begin
          procedureA(data ..., work_id);
          exception
            when dup_val_on_index then
              update_both(data ..., work_id);
            when others then rollback;
        end;
      end loop;
    end;
    

    我希望这能帮助像我这样的人:D

    • 随时欢迎其他建议