0

我有一个代表项目分组的表( 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 );

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

谢谢
皮耶罗

4

1 回答 1

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;
于 2012-09-18T11:32:02.803 回答