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

RowId-Wert in verschachtelte Tabelle einschließen

ROWID ist eine Pseudospalte , ist es nicht Teil der Datenwörterbuchansicht der Tabelle (z. B. erscheint es nicht in dba_tab_columns ), also ist es nicht in %rowtype enthalten . Ein PL/SQL-Datensatz – aus dem Sie eine PL/SQL-Tabelle erstellen – hat keinen physischen Speicher, also keine echte oder Pseudo-Rowid.

Wenn Sie die Zeilen-ID wirklich in einem Datensatz/einer Tabelle speichern möchten, müssen Sie den Typ explizit deklarieren:

create or replace package dat_pkg is

    type typ_dat_rec is record (
        data_id     data_test.data_id%type,
        data_value  data_test.data_value%type,
        data_rowid  rowid);

    type typ_dat_tst is table of data_test%rowtype index by pls_integer;

    procedure proc_test (p_dat  typ_dat_tst);

end dat_pkg;
/

Sie können das Datensatzfeld nicht einfach rowid nennen Da es sich um einen Datentyp handelt, habe ich ihm data_ vorangestellt aber vielleicht bevorzugst du etwas anderes. Und dann müssen Sie diesen Feldnamen natürlich in Ihrem Paketkörper verwenden:

create or replace package body dat_pkg is

    procedure proc_test (p_dat  typ_dat_tst)
    is
    begin

        for i in 1..p_dat.count loop

            update  data_test        
            set     data_value  = p_dat(i).data_value  
            where   data_id     = p_dat(i).data_id
            and     rowid       = p_dat(i).data_rowid;

        end loop;

    end proc_test;

end dat_pkg;
/

Sie könnten, wie Sie vorgeschlagen haben, den gesamten Zeilentyp und speichern die Zeilen-ID als zwei Felder im Datensatztyp:

create or replace package dat_pkg is

    type typ_dat_rec is record (
        data_rec    data_test%rowtype,
        data_rowid  rowid);

    type typ_dat_tst is table of typ_dat_rec index by pls_integer;

    procedure proc_test (p_dat  typ_dat_tst);

end dat_pkg;
/

aber das macht den Bezug auf die Felder etwas umständlicher:

...
        for i in 1..p_dat.count loop

            update  data_test        
            set     data_value  = p_dat(i).data_rec.data_value  
            where   data_id     = p_dat(i).data_rec.data_id
            and     rowid       = p_dat(i).data_rowid;

        end loop;
...

und es wird wahrscheinlich auch das Auffüllen der Sammlung umständlicher machen. Da Sie sowieso alle Spalten-/Feldnamen kennen müssen, um in der Schleife auf sie verweisen zu können, bin ich mir nicht sicher, ob es einen großen Vorteil gibt, aber Sie finden es vielleicht übersichtlicher.

Wenn Sie dies überhaupt tun, wird natürlich davon ausgegangen, dass Ihre Sammlung aus einer Teilmenge von Daten aus der Tabelle in derselben Datenbank und sogar in derselben Sitzung gefüllt wird, da die rowid einer Zeile können sich im Laufe der Zeit ändern. Vielleicht möchten Sie auch in forall nachsehen Syntax zum Ersetzen Ihres for Schleife, je nachdem, was Sie wirklich tun. (Aber Sie sollten auch überlegen, ob Sie die Sammlung überhaupt brauchen - wenn Sie nur die Sammlung füllen und diese dann für das Update verwenden, dann wäre ein einzelnes SQL-Update noch schneller ...)