【问题标题】:Update multiple table column values using single query使用单个查询更新多个表列值
【发布时间】:2011-02-11 07:31:39
【问题描述】:

如何使用单个查询更新多个表中的数据?

MySQL 示例

MySQL 中的等效代码:

更新方p 左加入party_name n ON p.party_id = n.party_id 左加入party_details d ON p.party_id = d.party_id 左加入 event_participant ip ON ip.party_id = p.party_id LEFT JOIN 事件 i ON ip.incident_id = i.incident_id 放 p.employee_id = NULL, c.em_address = 'x@x.org', c.ad_postal = 'x', n.first_name = 'x', n.last_name = 'x' 在哪里 i.confidential_dt 不为空

使用 Oracle 11g 的相同语句是什么?

谢谢!

RTFM

使用Oracle时似乎单个查询是不够的:

http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96540/statements_108a.htm#2067717

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:
    /** XXX CODING HORROR... */
    

    根据您的需要,您可以使用可更新视图。您创建一个基表视图并向该视图添加一个“代替”触发器,然后直接更新该视图。

    一些示例表:

    create table party (
        party_id integer,
        employee_id integer
        );
    
    create table party_name (
        party_id integer,
        first_name varchar2(120 char),
        last_name varchar2(120 char)
        );
    
    insert into party values (1,1000);   
    insert into party values (2,2000);
    insert into party values (3,3000);
    
    insert into party_name values (1,'Kipper','Family');
    insert into party_name values (2,'Biff','Family');
    insert into party_name values (3,'Chip','Family');
    
    commit;
    
    select * from party_v;
    
    PARTY_ID    EMPLOYEE_ID    FIRST_NAME    LAST_NAME
    1            1000           Kipper        Family
    2            2000           Biff          Family
    3            3000           Chip          Family
    

    ...然后创建一个可更新的视图

    create or replace view party_v
    as
    select
        p.party_id,
        p.employee_id,
        n.first_name,
        n.last_name
    from
        party p left join party_name n on p.party_id = n.party_id;
    
    create or replace trigger trg_party_update
    instead of update on party_v 
    for each row
    declare
    begin
    --
        update party
        set
            party_id = :new.party_id,
            employee_id = :new.employee_id
        where
            party_id = :old.party_id;
    --
        update party_name
        set
            party_id = :new.party_id,
            first_name = :new.first_name,
            last_name = :new.last_name
        where
            party_id = :old.party_id;
    --
    end;
    /
    

    您现在可以直接更新视图...

    update party_v
    set
        employee_id = 42,
        last_name = 'Oxford'
    where
        party_id = 1;
    
    select * from party_v;
    
    PARTY_ID    EMPLOYEE_ID    FIRST_NAME    LAST_NAME
    1            42             Kipper        Oxford
    2            2000           Biff          Family
    3            3000           Chip          Family
    

    【讨论】:

    • 谢谢你,尼克。可悲的是,这比仅仅创建三个不同的更新语句都具有相同的 where 子句要多得多的工作。这更难维护(表、视图和触发器与具有三个更新语句的一个过程相比)。在出现更好的解决方案之前,您的解决方案将获胜。 ;-)
    【解决方案2】:

    我遇到了同样的问题,我在 Oracle 中找不到简单的方法。

    看这里: Oracle Update Statements 了解更多信息。

    【讨论】:

      【解决方案3】:

      您可以使用 Oracle MERGE 语句来执行此操作。它是一种基于将目标表与内联视图连接起来的批量更新或插入语句。

      MERGE INTO bonuses D
         USING (
            SELECT employee_id, salary, department_id FROM employees
            WHERE department_id = 80
         ) S ON (D.employee_id = S.employee_id)
       WHEN MATCHED THEN 
         UPDATE SET D.bonus = D.bonus + S.salary*.01
       WHEN NOT MATCHED THEN 
         INSERT (D.employee_id, D.bonus)
         VALUES (S.employee_id, S.salary*0.1);
      

      如果您不需要插入部分,您只需省略上面的最后 3 行即可。

      【讨论】:

      • 虽然您的问题是关于同时更新多个表 - 不是 MERGE 的选项。
      【解决方案4】:

      在某些情况下,可以使用 PL/SQL 来实现这一点。在我的例子中,我通过一些条件在两个表中搜索匹配的行,然后循环更新每一行。

      类似这样的:

      begin
        for r in (
          select t1.id as t1_id, t2.id as t2_id
          from t1, t2
          where ...
        ) loop
          update t1
          set ...
          where t1.id = r.t1_id;
      
          update t2
          set ...
          where t2.id = r.t2_id;
        end loop;
      end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多