>我有下面的示例表:
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更新会更快...