ROWID
è una pseudocolonna
, non fa parte della vista del dizionario dei dati della tabella (ad es. non appare in dba_tab_columns
), quindi non è incluso nel %rowtype
. Un record PL/SQL, che è ciò di cui stai costruendo una tabella PL/SQL, non ha memoria fisica, quindi nessun ID reale o pseudo.
Se vuoi davvero memorizzare l'ID riga in un record/tabella dovresti dichiarare il tipo in modo esplicito:
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;
/
Non puoi chiamare il campo del record solo rowid
poiché è un tipo di dati, quindi l'ho preceduto con data_
ma potresti preferire qualcos'altro. E poi devi usare quel nome di campo nel corpo del tuo pacchetto, ovviamente:
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;
/
Potresti, come hai suggerito, memorizzare l'intero tipo di riga e l'ID riga come due campi nel tipo di record:
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;
/
ma questo rende un po' più imbarazzante fare riferimento ai campi:
...
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;
...
e probabilmente renderà anche più imbarazzante popolare la raccolta. Dato che devi comunque conoscere tutti i nomi di colonne/campi per poterli fare riferimento nel ciclo, non sono sicuro che ci siano molti vantaggi, ma potresti trovarlo più ordinato.
Ovviamente, fare questo presuppone che la tua raccolta venga popolata da un sottoinsieme di dati dalla tabella nello stesso DB e persino nella stessa sessione, poiché il rowid
di una riga può cambiare nel tempo. Potresti anche voler esaminare il forall
sintassi per sostituire il tuo for
loop, a seconda di cosa stai facendo veramente. (Ma dovresti anche considerare se hai bisogno della raccolta:se stai solo popolando la raccolta e quindi la usi per l'aggiornamento, un singolo aggiornamento SQL sarebbe ancora più veloce...)