Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Aktualisieren Sie die Ergebnisse einer SELECT-Anweisung

Ich habe keinen offiziellen Namen dafür gesehen. Die Oracle SQL Reference bezieht sich nur auf das Aktualisieren einer Unterabfrage. Ich neige dazu, es als eine Form der "Ansichtsaktualisierung" zu betrachten, wobei die Unterabfrage in der Inline-Ansicht angezeigt wird.

Ja, es funktioniert, wenn mehrere Tabellen zusammengeführt werden, aber es gelten die Regeln der Ansichtsaktualisierung. Das bedeutet, dass nur eine der Basistabellen der Ansicht aktualisiert werden kann und diese Tabelle in der Ansicht "schlüsselerhalten" sein muss:d. h. ihre Zeilen sollten nur einmal in der Ansicht erscheinen können. Dies erfordert, dass alle anderen Tabellen in der Ansicht (Unterabfrage) über Fremdschlüsseleinschränkungen auf die zu aktualisierende Tabelle verwiesen werden.

Einige Beispiele können helfen. Unter Verwendung der Standard-Oracle-Tabellen EMP und DEPT, wobei EMP.EMPNO als Primärschlüssel von EMP und EMP.DEPTNO als Fremdschlüssel für DEPT.DEPTNO definiert ist, ist diese Aktualisierung zulässig:

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

Aber das ist nicht:

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

Was die Leistung betrifft:Der Optimierer wird (muss) die zu aktualisierende Basistabelle während des Parsens identifizieren, und Verknüpfungen mit anderen Tabellen werden ignoriert, da sie keinen Einfluss auf die durchzuführende Aktualisierung haben – wie diese AUTOTRACE-Ausgabe zeigt:

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

(Beachten Sie, dass auf die Tabelle DEPT nie zugegriffen wird, obwohl DEPT.DNAME in der Unterabfrage erscheint).