ROWID
est une pseudo-colonne
, il ne fait pas partie de la vue du dictionnaire de données de la table (par exemple, il n'apparaît pas dans dba_tab_columns
), il n'est donc pas inclus dans le %rowtype
. Un enregistrement PL/SQL - dont vous construisez une table PL/SQL - n'a pas de stockage physique, donc pas de rowid réel ou pseudo.
Si vous voulez vraiment stocker l'ID de ligne dans un enregistrement/table, vous devrez déclarer le type explicitement :
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;
/
Vous ne pouvez pas appeler le champ d'enregistrement simplement rowid
comme il s'agit d'un type de données, je l'ai donc préfixé avec data_
mais vous pourriez préférer autre chose. Et puis vous devez utiliser ce nom de champ dans le corps de votre package, évidemment :
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;
/
Vous pouvez, comme vous l'avez suggéré, stocker le type de ligne entier et l'ID de ligne sous la forme de deux champs dans le type d'enregistrement :
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;
/
mais cela rend la référence aux champs un peu plus gênante :
...
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;
...
et cela rendra probablement le remplissage de la collection plus gênant aussi. Comme vous devez de toute façon connaître tous les noms de colonnes/champs pour pouvoir vous y référer dans la boucle, je ne suis pas sûr qu'il y ait beaucoup d'avantages, mais vous trouverez peut-être cela plus propre.
Bien sûr, cela suppose que votre collection est remplie à partir d'un sous-ensemble de données de la table dans la même base de données et même session, car le rowid
d'une ligne peut changer avec le temps. Vous pouvez également consulter le forall
syntaxe pour remplacer votre for
boucle, selon ce que vous faites réellement. (Mais vous devez également déterminer si vous avez besoin de la collection - si vous remplissez simplement la collection et que vous l'utilisez ensuite pour la mise à jour, une seule mise à jour SQL serait encore plus rapide...)