ROWID
är en pseudokolumn
, det är inte en del av datalexikonet i tabellen (det visas t.ex. inte i dba_tab_columns
), så det ingår inte i %rowtype
. En PL/SQL-post - vilket är vad du konstruerar en PL/SQL-tabell av - har ingen fysisk lagring, så ingen riktig eller pseudo-rowid.
Om du verkligen vill lagra rad-ID i en post/tabell måste du uttryckligen deklarera typen:
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;
/
Du kan inte anropa postfältet bara rowid
eftersom det är en datatyp, så jag har prefixet den med data_
men du kanske föredrar något annat. Och sedan måste du använda det fältnamnet i paketets kropp, uppenbarligen:
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;
/
Du kan, som du föreslog, lagra hela radtypen och rad-ID:t som två fält i posttypen:
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;
/
men det gör hänvisningen till fälten lite mer besvärlig:
...
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;
...
och det kommer förmodligen också att göra det svårare att fylla samlingen. Eftersom du ändå måste känna till alla kolumn-/fältnamn för att kunna referera till dem i slingan är jag inte säker på att det finns någon större fördel, men du kanske tycker att det är snyggare.
Att göra detta överhuvudtaget förutsätter naturligtvis att din samling fylls på från en delmängd av data från tabellen i samma DB och jämna session, eftersom en rads rowid
kan förändras över tiden. Du kanske också vill titta på forall
syntax för att ersätta din for
loop, beroende på vad du verkligen gör. (Men du bör också överväga om du behöver samlingen överhuvudtaget - om du bara fyller i samlingen och sedan använder den för uppdateringen så skulle en enda SQL-uppdatering vara snabbare...)