【问题标题】:conditional UPDATE in ORACLE with subqueryORACLE 中带有子查询的条件更新
【发布时间】:2012-09-10 15:32:36
【问题描述】:

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

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

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

第三步是从组中减去记录数/我需要显示的其他字段的总和,然后将它们添加到新组中,我可以在 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 );

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

谢谢
皮耶罗

【问题讨论】:

    标签: oracle subquery dml


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 2012-07-20
      相关资源
      最近更新 更多