sql >> Base de Datos >  >> RDS >> Oracle

Actualizar los resultados de una instrucción SELECT

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

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

Algunos ejemplos pueden ayudar. Usando las tablas estándar EMP y DEPT de Oracle, con EMP.EMPNO definido como la clave principal de EMP y EMP.DEPTNO definido como una clave externa para DEPT.DEPTNO, entonces se permite 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 al rendimiento:el optimizador identificará (debe) identificar la tabla base que se actualizará durante el análisis, y se ignorarán las uniones a otra tabla, ya que no tienen ninguna relación con la actualización que se realizará, como muestra este resultado de 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")

(Tenga en cuenta que nunca se accede a la tabla DEPT aunque DEPT.DNAME aparece en la subconsulta).