Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Atualizar os resultados de uma instrução SELECT


Não vi um nome formal para isso. A Referência do Oracle SQL apenas se refere à atualização de uma subconsulta. Eu costumo pensar nisso como uma forma de "atualização de exibição", com a subconsulta em exibição em linha.

Sim, funciona quando várias tabelas são unidas, mas sujeitas às regras de atualização de visualização. Isso significa que apenas uma das tabelas base da visão pode ser atualizada, e essa tabela deve ser "preservada por chave" na visão:ou seja, suas linhas devem poder aparecer apenas uma vez na visão. Isso requer que quaisquer outras tabelas na exibição (subconsulta) sejam referenciadas por meio de restrições de chave estrangeira na tabela a ser atualizada.

Alguns exemplos podem ajudar. Usando as tabelas padrão Oracle EMP e DEPT, com EMP.EMPNO sendo definido como a chave primária de EMP e EMP.DEPTNO sendo definido como uma chave estrangeira para DEPT.DEPTNO, então esta atualização é permitida:
update (select emp.empno, emp.ename, emp.sal, dept.dname
        from   emp join dept on dept.deptno = emp.deptno
       )
set sal = sal+100;

Mas isso não é:
-- 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);

Quanto ao desempenho:o otimizador (deve) identificar a tabela base a ser atualizada durante a análise, e as junções a outra tabela serão ignoradas, pois não têm influência na atualização a ser realizada - como mostra esta saída do 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")

(Observe que a tabela DEPT nunca é acessada, embora DEPT.DNAME apareça na subconsulta).