2009-06-16 13 views
6

Oracle le permite actualizar los resultados de una instrucción SELECT.Actualice los resultados de una instrucción SELECT

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

supongo que esto podría ser utilizado para las columnas de actualización en una tabla basada en el valor de una fila coincidente en la otra tabla.

¿Cómo se llama esta característica? ¿Se puede usar de manera eficiente para grandes actualizaciones? ¿Funciona cuando el SELECT se une a varias tablas y, de ser así, cómo?

+2

Hay un ejemplo de una actualización de una unión en otro SO: http://stackoverflow.com/questions/975315/what-is-wrong-with-my-update-statement-with-a-join-in- oracle/975674 # 975674 - Con respecto a la eficiencia: es probablemente la forma más eficiente de actualizar un conjunto de filas –

+1

Generalmente se llama actualización de vista. –

Respuesta

1

Gracias por los comentarios, pensé que esto era estándar SQL ... :(

Para Oracle puede escribir una actualización sobre una mesa en la que recuperar la información con una unión como:

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

Para SQL Server, que es:

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

Si alguien conoce una manera de hacer esto que funciona en Oracle, SQL Server y MySQL estaría interesado

.
+1

¿Estás seguro de que funciona? En Oracle, obtengo "ORA-00933: el comando SQL no terminó correctamente" en "FROM"? – Thilo

+0

Usando http://www.dpriver.com/pp/sqlformat.htm parece que funciona para MSSQL, pero proporciona errores de sintaxis para Oracle, MySQL o DB2 – Thilo

+0

-1 No, no funciona en Oracle. No estoy seguro de que sea SQL estándar tampoco. –

1

El formulario que menciona no tiene un nombre específico AFAIK. Simplemente actualizando el resultado de una declaración seleccionada.

Hay otra forma llamada actualización correlacionada (con la actualización de una o de varias columnas)

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

La forma de varias columnas

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

También hay una de la que también regresar de valores llamados actualización con la cláusula de retorno

Y algunos específicos s para actualizaciones con tablas anidadas. Lo mejor es marcar al menos dos páginas de esta

Oracle® Database SQL Language Reference SELECT

Oracle® Database SQL Language Reference UPDATE

4

No he visto un nombre formal para esto. El Oracle SQL Reference solo se refiere a la actualización de una subconsulta. Tiendo a pensar en ello como una forma de "ver la actualización", con la subconsulta en la vista en línea.

Sí, funciona cuando se unen varias tablas, pero está sujeto a la actualización de las reglas de visualización. Esto significa que solo se puede actualizar una de las tablas base de la vista, y esta tabla debe conservarse "clave" en la vista: es decir, sus filas solo deberían poder aparecer una vez en la vista. Esto requiere que cualquier otra tabla en la vista (subconsulta) se haga referencia a través de restricciones de clave externa en la tabla que se actualizará.

Algunos ejemplos pueden ayudar. Uso de las tablas estándares de Oracle EMP y DEPT, con EMP.EMPNO definido como la clave principal de EMP, y EMP.DEPTNO definido como una clave externa para DEPT.DEPTNO, a continuación, se permite que esta actualización

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

Pero esto no es:

-- 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); 

En cuanto a rendimiento: el optimizador (debe) identificar la tabla base que se actualiza durante el análisis, y se une a otra tabla será ignorado, ya que no tienen ninguna relación con la actualización que se realiza - como esta AUTOTRACE salida muestra:

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") 

(Tenga en cuenta que la tabla DEPT Nunca se accede a pesar de que appe DEPT.DNAME ars en la subconsulta).

Cuestiones relacionadas