2010-04-22 102 views
3

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

的MySQL实例

等效在MySQL代码:

 
UPDATE party p 
LEFT JOIN party_name n ON p.party_id = n.party_id 
LEFT JOIN party_details d ON p.party_id = d.party_id 
LEFT JOIN incident_participant ip ON ip.party_id = p.party_id 
LEFT JOIN incident i ON ip.incident_id = i.incident_id 
SET 
    p.employee_id = NULL, 
    c.em_address = '[email protected]', 
    c.ad_postal = 'x', 
    n.first_name = 'x', 
    n.last_name = 'x' 
WHERE 
    i.confidential_dt IS NOT NULL 

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

谢谢!

RTFM

看来当使用一个单一的查询是不够的甲骨文:

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

回答

5
/** 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 
+1

感谢你,尼克。令人遗憾的是,除了用同样的where子句创建三个不同的更新语句之外,还有很多工作要做。这更难以维护(表格,视图和触发器与具有三条更新语句的一个过程)。直到有更好的解决方案出现,你的胜利。 ;-) – 2010-04-23 16:45:58

1

我有同样的问题,我无法找到一个简单的方法在Oracle中做到这一点。

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

1

您可以使用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行。

+0

虽然你的问题是关于同时更新多个表 - 不能与MERGE一个选项。 – 2010-04-23 08:34:13

+0

糟糕 - 你说得很对 - 误解了这个问题。对不起 – 2010-04-23 11:28:38

1

在某些情况下,可以使用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;