带子查询的ORACLE中的条件UPDATE

时间:2012-09-18 11:10:33

标签: oracle subquery dml

我有一个表(item1)表示项目分组,另一个表(table2)表示项目本身。
table1.id是table2的外键,在table1的每个记录中,我还收集信息,如table2中与该特定记录关联的记录总数以及各个字段的总和,以便我可以显示分组和所在内容的摘要。它无需查询table2 通常一次添加/删除table2中的项目,因此我更新table1以反映table2中的更改。

出现了新要求,必须将选择组中的项目移至新组。我认为这是一个三步操作:

  1. 在table1中创建一个新组
  2. 更新选择table2中的记录以指向table1
  3. 中新创建的rec

    第三步是向组中减去记录数/我需要显示的其他字段的总和并将它们添加到新组中,我可以找到的数据只是查询table2以查找与新组关联的项目基。

    我想出了以下有效的陈述。

    update table1 t1 set 
    countitems = ( 
        case t1.id 
          when 1 then t1.countitems - ( select count( t2.id ) from table2 t2 where t2.id = 2 )
          when 2 then ( select count( t2.id ) from table2 t2 where t2.id = 2 )
        end
    ), 
    sumitems = (
        case t1.id
          when 1 then t1.sumitems - ( select sum( t2.num ) from table2 t2 where t2.id = 2 )
          when 2 then ( select sum( t2.num ) from table2 t2 where t2.id = 2 )
        end
    )
    where t1.id in( 1, 2 );
    

    有没有办法重写语句而不必每次都重复子查询?

    感谢
    皮耶罗

1 个答案:

答案 0 :(得分:0)

您可以在rowid上使用游标和批量收集更新语句。这样,您可以简单地使用所需结果编写连接查询,并使用这些值更新表。我总是使用这个功能,每次都做一些调整。

declare
    cursor cur_cur
    IS
    select ti.rowid     row_id
    ,      count(t2.id) countitems
    ,      sum(t2.num)  numitems
    from   table t1
    join   table t2 on t1.id = t2.t1_id
    order by row_id
    ;

    type type_rowid_array is table of rowid index by binary_integer;
    type type_countitems_array is table of table1.countitems%type;
    type type_numitems_array is table of table1.numitems%type;

    arr_rowid type_rowid_array;
    arr_countitems type_countitems_array;
    arr_numitems type_numitems_array;

    v_commit_size number := 10000;

begin
    open cur_cur;

    loop
        fetch cur_cur bulk collect into arr_rowid, arr_countitems, arr_numitems limit v_commit_size;

        forall i in arr_rowid.first .. arr_rowid.last
            update table1 tab
            SET    tab.countitems = arr_countitems(i)
            ,      tab.numitems = arr_numitems(i)
            where  tab.rowid = arr_rowid(i)
            ;

        commit;
        exit when cur_cur%notfound;

    end loop;

    close cur_cur;
    commit;

exception
  when others
    then rollback;
         raise_application_error(-20000, 'ERROR updating table1(countitems,numitems) - '||sqlerrm);

end;