2009-06-16 97 views
6

Oracle允许您更新SELECT语句的结果。更新SELECT语句的结果

UPDATE (<SELECT Statement>) 
SET <column_name> = <value> 
WHERE <column_name> <condition> <value>; 

我想这可以用于基于另一个表中匹配行的值更新一个表中的列。

该功能是如何调用的,它可以有效地用于大型更新,当SELECT连接多个表时它是否工作,如果是这样,如何工作?

+2

有一个例子在另一个连接更新的例子:http://stackoverflow.com/questions/975315/what-is-wrong-with-my-update-statement-with-a-join-in- oracle/975674#975674 - 关于效率:它可能是更新一组行的最有效方式 – 2009-06-16 09:21:51

+1

它通常称为视图更新。 – 2009-06-16 09:56:13

回答

1

感谢的意见,我认为这是标准的SQL ... :(

对于Oracle,你可以在桌子上写的更新,你用检索信息加入这样的:

UPDATE (
    SELECT * 
    FROM table1 t1 
    LEFT JOIN table2 t2 ON t2.t1id = t1.ID 
) SET t1.col1 = t2.col2 

对于SQL Server中,它是:

UPDATE t1 
SET col1 = t2.col2 
FROM table1 t1 
LEFT JOIN table2 t2 on t2.t1id = t1.id 

如果有人知道的方式来做到这一点在Oracle,SQL Server和MySQL的作品我有兴趣

1

您提到的表单没有具体的名称AFAIK。只需更新select语句的结果即可。

有一个称为相关更新(与单或多列更新)另一种形式

UPDATE TABLE(<SELECT STATEMENT>) <alias> 
SET <column_name> = (
    SELECT <column_name> 
    FROM <table_name> <alias> 
    WHERE <alias.table_name> <condition> <alias.table_name> 
); 

的多列形式

... 
SET (<column_name_list>) = (
    SELECT <column_name_list> 
... 

还有一个从它也返回值的称为更新带退货条款

还有一些具体的s用嵌套表进行更新。最好是检查

Oracle® Database SQL Language Reference SELECT

Oracle® Database SQL Language Reference UPDATE

4

我还没有为这个看到一个正式的名字,至少这两个页面。 Oracle SQL Reference只是指更新子查询。我倾向于将其视为“视图更新”的一种形式,子查询处于内联视图。

是的,它适用于多个表加入时,但受到视图更新规则的约束。这意味着只能更新视图基表中的一个,并且该表必须在视图中保留为“键保留”状态:即其行必须只能在视图中出现一次。这要求视图(子查询)中的任何其他表都通过要更新的表上的外键约束来引用。

一些示例可能有所帮助。使用标准Oracle EMP和DEPT表,并将EMP.EMPNO定义为EMP的主键,并将EMP.DEPTNO定义为DEPT的外键。DEPTNO,那么这个更新是允许的:

update (select emp.empno, emp.ename, emp.sal, dept.dname 
     from emp join dept on dept.deptno = emp.deptno 
     ) 
set sal = sal+100; 

但是,这并不:

-- DEPT is not "key-preserved" - same DEPT row may appear 
-- several times in view 
update (select emp.ename, emp.sal, dept.deptno, dept.dname 
     from emp join dept on dept.deptno = emp.deptno 
     ) 
set dname = upper(dname); 

至于性能:优化器会(必须)确定基本表分析过程中进行更新,并加入到其他表将被忽略,因为他们没有上进行更新任何影响 - 因为这AUTOTRACE输出显示:

SQL> update (select emp.ename, emp.sal, dept.dname 
    2    from emp join dept on dept.deptno = emp.deptno 
    3   ) 
    4  set sal = sal-1; 

33 rows updated. 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1507993178 

------------------------------------------------------------------------------------ 
| Id | Operation   | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------ 
| 0 | UPDATE STATEMENT |    | 33 | 495 |  3 (0)| 00:00:01 | 
| 1 | UPDATE    | EMP   |  |  |   |   | 
| 2 | NESTED LOOPS  |    | 33 | 495 |  3 (0)| 00:00:01 | 
| 3 | TABLE ACCESS FULL| EMP   | 33 | 396 |  3 (0)| 00:00:01 | 
|* 4 | INDEX UNIQUE SCAN| SYS_C0010666 |  1 |  3 |  0 (0)| 00:00:01 | 
------------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO") 

(请注意,表DEPT从未访问即使DEPT.DNAME APPE子查询中的ars)。