我有一个表(item1)表示项目分组,另一个表(table2)表示项目本身。
table1.id是table2的外键,在table1的每个记录中,我还收集信息,如table2中与该特定记录关联的记录总数以及各个字段的总和,以便我可以显示分组和所在内容的摘要。它无需查询table2
通常一次添加/删除table2中的项目,因此我更新table1以反映table2中的更改。
出现了新要求,必须将选择组中的项目移至新组。我认为这是一个三步操作:
第三步是向组中减去记录数/我需要显示的其他字段的总和并将它们添加到新组中,我可以找到的数据只是查询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 );
有没有办法重写语句而不必每次都重复子查询?
感谢
皮耶罗
答案 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;