Sql 更新SELECT语句的结果

Sql 更新SELECT语句的结果,sql,oracle,sql-update,bulk,Sql,Oracle,Sql Update,Bulk,Oracle允许您更新SELECT语句的结果 UPDATE (<SELECT Statement>) SET <column_name> = <value> WHERE <column_name> <condition> <value>; 我想这可以用于根据另一个表中匹配行的值更新一个表中的列 这项功能是如何调用的,它能否有效地用于大型更新,当SELECT连接多个表时它是否工作,如果是,如何工作?感谢您的评论,我认为这是标

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

UPDATE (<SELECT Statement>)
SET <column_name> = <value>
WHERE <column_name> <condition> <value>;
我想这可以用于根据另一个表中匹配行的值更新一个表中的列


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

感谢您的评论,我认为这是标准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上运行的方法,我会感兴趣。

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

UPDATE (<SELECT Statement>)
SET <column_name> = <value>
WHERE <column_name> <condition> <value>;
还有另一种形式称为关联更新和单列或多列更新

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>
...
还有一个名为Update with returning子句的返回值的语句

以及使用嵌套表进行更新的一些细节。最好是至少检查这两页


我还没有看到这个的正式名称。这只是指更新子查询。我倾向于将其视为视图更新的一种形式,子查询位于内嵌视图中

是的,它在多个表被联接时工作,但受视图更新规则的约束。这意味着只能更新视图的一个基表,并且该表必须在视图中保留键:即其行在视图中只能显示一次。这要求通过要更新的表上的外键约束引用视图子查询中的任何其他表

一些例子可能会有所帮助。使用标准的Oracle EMP和DEPT表,将EMP.EMPNO定义为EMP的主键,将EMP.DEPTNO定义为dep.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);
至于性能:优化程序必须在解析过程中识别要更新的基表,而与其他表的连接将被忽略,因为它们对要执行的更新没有任何影响-如此自动跟踪输出所示:

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.DNAME出现在子查询中,也不会访问表DEPT。

是否确实有效?在Oracle中,我得到ORA-00933:SQL命令未正确地结束于FROM?使用它似乎对MSSQL有效,但对Oracle、MySQL或DB2-1给出了语法错误。不,它在Oracle中不起作用。我也不确定它是否是标准SQL。有一个例子是在另一个SO中更新联接:-关于效率:这可能是更新一组行的最有效的方法,通常称为视图更新。