Oracle
 sql >> Base de données >  >> RDS >> Oracle

Mettre à jour les résultats d'une instruction SELECT

Je n'ai pas vu de nom officiel pour cela. La Référence Oracle SQL fait simplement référence à la mise à jour d'une sous-requête. J'ai tendance à le considérer comme une forme de "mise à jour de la vue", la sous-requête étant en vue en ligne.

Oui, cela fonctionne lorsque plusieurs tables sont jointes, mais sous réserve des règles de mise à jour des vues. Cela signifie qu'une seule des tables de base de la vue peut être mise à jour, et cette table doit être "à clé préservée" dans la vue :c'est-à-dire que ses lignes ne doivent pouvoir apparaître qu'une seule fois dans la vue. Cela nécessite que toutes les autres tables de la vue (sous-requête) soient référencées via des contraintes de clé étrangère sur la table à mettre à jour.

Quelques exemples peuvent aider. En utilisant les tables standard Oracle EMP et DEPT, avec EMP.EMPNO étant défini comme clé primaire d'EMP, et EMP.DEPTNO étant défini comme clé étrangère de DEPT.DEPTNO, cette mise à jour est autorisée :

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

Mais ce n'est pas :

-- 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 ce qui concerne les performances :l'optimiseur identifiera (doit) la table de base à mettre à jour lors de l'analyse, et les jointures à d'autres tables seront ignorées car elles n'ont aucune incidence sur la mise à jour à effectuer - comme le montre cette sortie 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")

(Notez que la table DEPT n'est jamais accessible même si DEPT.DNAME apparaît dans la sous-requête).