2017-05-16 5 views
0

ich die folgende Beispieltabelle habe:Fügen RowId Wert in geschachtelten Tabelle

create table data_test 
(
    data_id  number, 
    data_value varchar2(100) 
); 

Ich möchte dies als Parameter, indem Sie die folgende Erklärung in dem folgende Beispiel Stored Procedure verschachtelter Tabelle verwenden:

create or replace package dat_pkg is 

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

ich möchte proc_test die Zeilen von data_test basierend aktualisieren auf der rowid der verschachtelten Tabelle:

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

     end loop; 

    end proc_test; 

end dat_pkg; 
/ 

jedoch bekomme ich den Fehler PLS-00302: component 'ROWID' must be declared, weil es nach der physischen Spalte rowid in der geschachtelten Tabelle sucht. Der gleiche Fehler wird ausgelöst, wenn ich die Funktion rowidtochar() verwende.

Wie kann ich rowid als eine physische Spalte in der Typ-Deklaration einschließen?

Antwort

1

ROWID is a pseudocolumn, es ist nicht Teil der Data Dictionary-Ansicht der Tabelle (z. B. erscheint es nicht in dba_tab_columns), so ist es nicht in der %rowtype enthalten. Ein PL/SQL-Datensatz - woran Sie eine PL/SQL-Tabelle erstellen - hat keinen physischen Speicher, also keine echte oder Pseudo-Rowid.

Wenn Sie wirklich die Zeilen-ID in einem Datensatz/Tabelle speichern möchten, würden Sie den Typ explizit erklären müssen:

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 wie das nur rowid nennen, ist ein Datentyp , also habe ich es mit data_ vorangestellt, aber Sie bevorzugen vielleicht etwas anderes. Und dann müssen Sie in Ihrem Paket Körper, dass die Feldnamen verwenden, offensichtlich:

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, speichern Sie den gesamten Zeilentyp und der Zeilen-ID als zwei Felder in dem 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 auf die Felder unter Bezugnahme etwas umständlich:

... 
     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 die Sammlung mehr make a bevöl wkward auch. Da Sie sowieso alle Spalten-/Feldnamen kennen müssen, um sich auf sie in der Schleife beziehen zu können, bin ich mir nicht sicher, ob das von Vorteil ist, aber Sie finden es vielleicht besser.

Natürlich wird davon ausgegangen, dass Ihre Sammlung aus einer Teilmenge von Daten aus der Tabelle in der gleichen DB und sogar in der Sitzung gefüllt wird, da sich die Zeile rowid einer Zeile ändern kann. Vielleicht möchten Sie auch in die forall-Syntax suchen, um Ihre for-Schleife zu ersetzen, je nachdem, was Sie wirklich tun. (Aber Sie sollten auch überlegen, ob Sie die Sammlung überhaupt benötigen - wenn Sie nur die Sammlung füllen und dann für das Update verwenden, wäre ein einzelnes SQL-Update noch schneller ...)

+0

wäre es besser, wenn ich definiert es als unten? Typ typ_dat_rec ist Datensatz ( data_rec data_test% rowtype, data_rowid rowid); –

+0

Ich sehe nicht, dass das wirklich besser wäre, aber hängt vielleicht davon ab, wie Sie es benutzen. Es würde funktionieren, aber Sie würden eine andere Kennung haben, wenn Sie es verwenden, und es macht das Auffüllen der Sammlung schwieriger. –

+0

Danke für das Hinzufügen des Vorschlags, der Grund, warum ich die Verwendung eines '% rowType 'vorgeschlagen habe, war, weil ich ungefähr 100 Spalten in dieser Tabelle habe und es wäre etwas" unordentlich "für mich, sie in der Typspezifikation zu deklarieren. –

Verwandte Themen