在Oracle中有效地更新表

时间:2016-10-12 05:18:11

标签: sql database oracle

我有3个表A(a1,a2),B(b1,b2),C(c1,c2)。我想以下列方式执行更新:

UPDATE A 
SET A.a2 =   (SELECT 2* SUM(C.c2) 
             FROM B JOIN C 
             ON B.b1 = C.c1 WHERE A.a1 = B.b2) 
WHERE A.a1 = (SELECT B.b2 
             FROM B JOIN C 
             ON B.b1 = C.c1 HAVING SUM(C.c2) > 1000); 

这种方法的问题是表B和C需要连接多次。

有什么好的解决方案可以解决这个问题吗?

我试过了:

UPDATE A SET A.a2 = (SELECT CASE 
                            WHEN SUM(C.c2) > 1000 THEN 2*SUM(C.c2) 
                            ELSE A.a2 
                            END
                     FROM B JOIN C 
                     ON B.b1 = C.c1 
                     WHERE A.a1 = B.b2);

但它不使用a1上的索引,它也会更新表A中的所有行,这比原来的行还要慢

3 个答案:

答案 0 :(得分:1)

使用MERGE代替时,这种更新通常会更快:

MERGE INTO a
using
(
   SELECT b.b2, 2 * SUM(C.c2)  as c2_sum
   FROM B 
     JOIN C ON B.b1 = C.c1 
   group by b.b2
   HAVING SUM(C.c2) > 1000
) t on (t.b2 = a.a1)
when matched then update 
     set a2 = t.c2_sum;

答案 1 :(得分:0)

如果它的操作非常长,您可以创建计算结果的中间表。但是你需要在两个表上都有主键

 Create table int_a as 
 SELECT 2* SUM(C.c2) as new_a2
       , B.b2 
         FROM B JOIN C 
         ON B.b1 = C.c1 WHERE A.a1 = B.b2
         GROUP BY B.b2 
         HAVING SUM(C.c2) > 1000

 alter table int_a add constraint primary key pk_int_a (b2);
 alter table a add constraint primary key pk_a (a2);

并使用join

更新表a
 update (select a2, int_a.new_a2
           from  A, INT_A
          where A.a1 = INT_A.b2)
    set a2 = new_a2

答案 2 :(得分:0)

您可以使用“with clause”

update A
   SET A.a2 =
       ((with data as (SELECT B.b2, C.c2 FROM B JOIN C ON B.b1 = C.c1)
         select *
           from data_b_c)
         select * from data b_c, A where A.a1 = b_c.b2 HAVING SUM(b_c.c2) > 1000)