在嵌套表中包括 RowId 值



>我有下面的示例表:

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

我想通过执行以下声明将其用作以下示例存储过程中的嵌套表参数:

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

我希望proc_test根据嵌套表的rowid更新data_test行:

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

但是我PLS-00302: component 'ROWID' must be declared收到错误,因为它在嵌套表中查找物理列 rowid。 当我使用函数rowidtochar()时,会引发相同的错误。

如何在类型声明中将rowid作为物理列包含在内?

ROWID

是一个伪列,它不是表的数据字典视图的一部分(例如,它不会出现在dba_tab_columns中),所以它不包含在%rowtype中。PL/SQL 记录 - 即您正在构建 PL/SQL 表的内容 - 没有物理存储,因此没有真实或伪 rowid。

如果您确实想将行 ID 存储在记录/表中,则必须显式声明类型:

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

您不能只rowid调用记录字段,因为它是一种数据类型,所以我在它前面加上了data_但您可能更喜欢其他内容。然后,您需要在包正文中使用该字段名称,显然:

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

您可以按照建议将整个行类型和行 ID 存储为记录类型中的两个字段:

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

但这会使引用字段变得更加尴尬:

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

而且它可能也会使填充集合更加尴尬。由于您必须知道所有列/字段名称才能在循环中引用它们,因此我不确定是否有太大优势,但您可能会发现它更整洁。

当然,这样做完全假设您的集合是从同一数据库甚至会话中的表中的数据子集填充的,因为行的rowid会随着时间的推移而变化。您可能还需要研究forall语法以替换for循环,具体取决于您实际在做什么。(但是您还应该考虑是否需要该集合 - 如果您只是填充集合然后将其用于更新,那么单个SQL更新会更快...

相关内容

  • 没有找到相关文章