我有以下示例表:
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
作为实体列?
答案 0 :(得分:1)
ROWID
is a pseudocolumn,它不是表格的数据字典视图的一部分(例如,它不会出现在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;
/
您可以按照建议将整个行类型和存储为记录类型中的两个字段:
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更新会更快...)