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

Aktualisieren Sie mehrere Datensätze in mehreren verschachtelten Tabellen in Oracle

Der vielleicht beste Grund, verschachtelte Tabellen in einer Datenbank zu vermeiden, ist, dass sie schwer zu handhaben sind und die Syntax unzureichend dokumentiert und schwer zu verstehen ist.

Weiter geht's!

Hier ist eine Tabelle mit einer verschachtelten Tabelle.

SQL> select f.force_name, t.id, t.name
  2  from transformer_forces f, table(f.force_members) t
  3  /

FORCE_NAME         ID NAME
---------- ---------- --------------------
Autobot             0 Metroplex
Autobot             0 Optimus Prime
Autobot             0 Rodimus
Decepticon          0 Galvatron
Decepticon          0 Megatron
Decepticon          0 Starscream
Dinobot             0 Grimlock
Dinobot             0 Swoop
Dinobot             0 Snarl

9 rows selected.

SQL>

Wie Sie sehen können, wird für jedes Element in der verschachtelten Tabelle das ID-Attribut in allen Fällen auf Null gesetzt. Wir möchten sie alle aktualisieren. Aber leider!

SQL> update table
  2   ( select force_members from transformer_forces ) t
  3  set t.id = rownum
  4  /
 ( select force_members from transformer_forces ) t
   *
ERROR at line 2:
ORA-01427: single-row subquery returns more than one row


SQL> 

Es ist möglich, alle Elemente einer verschachtelten Tabelle für eine einzelne Zeile in der Haltetabelle zu aktualisieren:

SQL> update table
  2       ( select force_members from transformer_forces
  3         where force_name = 'Autobot') t
  4      set t.id = rownum
  5  /

3 rows updated.

SQL>

Aber die einzige Möglichkeit, das zu tun denn die ganze Tabelle ist eine PL/SQL-Schleife. Yuck!

Es gibt eine Alternative:verwenden Sie eine verschachtelte Tabelle Locator , über den NESTED_TABLE_GET_REFS-Hinweis. Dies ist eine besonders obskure Sache (es ist nicht in Hauptliste der Hinweise ), aber es funktioniert:

SQL> update /*+ NESTED_TABLE_GET_REFS */ force_members_nt
  2  set id = rownum
  3  /

9 rows updated.

SQL> select f.force_name, t.id, t.name
  2  from transformer_forces f, table(f.force_members) t
  3  /

FORCE_NAME         ID NAME
---------- ---------- --------------------
Autobot             1 Metroplex
Autobot             2 Optimus Prime
Autobot             3 Rodimus
Decepticon          4 Galvatron
Decepticon          5 Megatron
Decepticon          6 Starscream
Dinobot             7 Grimlock
Dinobot             8 Swoop
Dinobot             9 Snarl

9 rows selected.

SQL>

Dieser Hinweis ermöglicht es uns, die Haltetabelle vollständig zu umgehen und mit der eigentlichen verschachtelten Tabelle zu arbeiten. Das heißt, das Objekt, das in der Nested Table-Speicherklausel angegeben ist:

create table transformer_forces (
    force_name varchar2(10)
    , force_members transformers_nt)
nested table force_members store as force_members_nt return as value;
                                    ^^^^^^^^^^^^^^^^