Oracle
 sql >> Database >  >> RDS >> Oracle

Aggiorna i risultati di un'istruzione SELECT

Non ho visto un nome formale per questo. Il Riferimento Oracle SQL si riferisce solo all'aggiornamento di una sottoquery. Tendo a considerarlo come una forma di "aggiornamento della vista", con la sottoquery nella visualizzazione in linea.

Sì, funziona quando si uniscono più tabelle, ma è soggetto alle regole di aggiornamento della vista. Ciò significa che è possibile aggiornare solo una delle tabelle di base della vista e questa tabella deve essere "conservata con chiave" nella vista:ovvero le sue righe dovrebbero poter apparire solo una volta nella vista. Ciò richiede che tutte le altre tabelle nella vista (sottoquery) siano referenziate tramite vincoli di chiave esterna sulla tabella da aggiornare.

Alcuni esempi possono aiutare. Utilizzando le tabelle Oracle EMP e DEPT standard, con EMP.EMPNO definito come chiave primaria di EMP e EMP.DEPTNO definito come chiave esterna per DEPT.DEPTNO, questo aggiornamento è consentito:

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

Ma questo non è:

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

Per quanto riguarda le prestazioni:l'ottimizzatore (deve) identificare la tabella di base da aggiornare durante l'analisi e i join ad altre tabelle verranno ignorati poiché non hanno alcun effetto sull'aggiornamento da eseguire, come mostra questo output di 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")

(Nota che la tabella DEPT non è mai accessibile anche se DEPT.DNAME appare nella sottoquery).