2011-08-18 62 views
3

我在使用Oracle 10g语法进行关联更新时遇到困难。我正在PL/SQL过程中处理此代码。Oracle关联更新

我会在SQL Server作为这样解决这个问题:

UPDATE table_a a 
SET  a.prov_id=pn.prov_id, 
     a.step=1 
from (
      SELECT p.prov_id 
      FROM note n 
      INNER JOIN provider p ON n.author_id=p.user_id 
      where n.enc_id=a.enc_id 
      AND  TRUNC(n.note_time)=a.attr_date 
     ) pn 

等效的Oracle语法为:

UPDATE table_a a 
SET  a.prov_id=(
      SELECT p.prov_id 
      FROM note n 
      INNER JOIN provider p ON n.author_id=p.user_id 
      where n.enc_id=a.enc_id 
      AND  TRUNC(n.note_time)=a.attr_date 
     ), 
     a.step=1 
WHERE EXISTS (
      SELECT * 
      FROM note n 
      INNER JOIN provider p ON n.author_id=p.user_id 
      where n.enc_id=a.enc_id 
      AND  TRUNC(n.note_time)=a.attr_date 
     ) 

这是否实际上运行子查询两次?是否有比这更简化的语法?

+0

查看SQL关键字'MERGE':SQL Server和Oracle均支持这两种SQL语言,均基于标准SQL,因此在这些SQL产品之间具有高度的可移植性。 – onedaywhen

回答

5

至于子查询是否运行两次,请使用EXPLAIN PLAN。

我喜欢用的,而不是更新这些相关的更新合并命令,像:(没有测试,如果你想有一个测试的回答,请提供DDL和insert语句。)

merge into table_a TRGT 
using (select P.prov_id, N.enc_id, trunc(n.note_time) as trunc_note_time 
    from note N 
    inner join provider P ON N.author_id=P.user_id) SRC 
on (TRGT.enc_id = SRC.enc_id and TRGT.attr_date = SRC.trunc_note_time) 
when matched then update set prov_id = SRC.prov_id 
    , step = 1 

有时候你可以更新内联视图,如下所示:

update (select A.prov_id, A.step, P.prov_id as p_prov_id 
    from note N 
    inner join provider P on N.author_id=p.user_id 
    inner join table_a A 
     on N.enc_id=A.enc_id 
     and trunc(N.note_time)=A.attr_date) 
set prov_id = p_prov_id 
    , step = 1 

内联视图版本不会总是有效。在错误中找不到信息,但实质上内联视图需要有一个唯一的密钥,Oracle可以将其绑定回有问题的表。