Oracle 关联 UPDATE

Posted

技术标签:

【中文标题】Oracle 关联 UPDATE【英文标题】:Oracle correlated UPDATE 【发布时间】:2011-08-18 19:52:16 【问题描述】:

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

我会这样处理 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
        )

这实际上会运行子查询两次吗?还有比这更缩写的语法吗?

【问题讨论】:

看一下 SQL 关键字MERGE:SQL Server 和 Oracle 都支持它,都基于标准 SQL,因此在这些 SQL 产品之间具有高度可移植性。 【参考方案1】:

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

我喜欢对这些相关更新使用合并命令而不是更新,例如:(未测试,如果您想要测试答案,请提供 DDL 和插入语句。)

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 可以将其绑定到相关表。

【讨论】:

以上是关于Oracle 关联 UPDATE的主要内容,如果未能解决你的问题,请参考以下文章

oracle 删除关联表数据

关于oracle 多表关联更新的问题

oracle 删除关联表数据

oracle 多表关联查询速度太慢了 ,求优化。。

(oracle)子查询和关联查询效率问题

oracle 三表关联查询