在嵌套中包含 RowId 值 Table
Include RowId value in Nested Table
我有以下示例 table:
create table data_test
(
data_id number,
data_value varchar2(100)
);
我想通过执行以下声明,在下面的示例存储过程中将其用作嵌套 table 参数:
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
根据嵌套 table 的 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
因为它在嵌套 Table 中寻找物理列 rowid。
当我使用函数 rowidtochar()
.
时出现同样的错误
如何在类型声明中包含 rowid
作为物理列?
ROWID
is a pseudocolumn,它不是 table 的数据字典视图的一部分(例如,它没有出现在 dba_tab_columns
中),因此它不包含在%rowtype
。 PL/SQL 记录 - 这是您正在构建的 PL/SQL table - 没有物理存储,因此没有真实或伪 rowid。
如果您真的想将行 ID 存储在 record/table 中,您必须显式声明类型:
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;
...
而且它可能也会使填充集合变得更加尴尬。因为无论如何您都必须知道所有 column/field 名称才能在循环中引用它们,所以我不确定这有什么好处,但您可能会发现它更简洁。
当然,这样做完全假设您的集合是从同一数据库甚至会话中 table 的数据子集填充的,因为一行的 rowid
会随时间变化.您可能还想查看 forall
语法来替换 for
循环,具体取决于您的实际操作。 (但是你也应该考虑你是否需要这个集合 - 如果你只是填充集合然后使用它进行更新那么单个 SQL 更新会更快......)
我有以下示例 table:
create table data_test
(
data_id number,
data_value varchar2(100)
);
我想通过执行以下声明,在下面的示例存储过程中将其用作嵌套 table 参数:
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
根据嵌套 table 的 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
因为它在嵌套 Table 中寻找物理列 rowid。
当我使用函数 rowidtochar()
.
如何在类型声明中包含 rowid
作为物理列?
ROWID
is a pseudocolumn,它不是 table 的数据字典视图的一部分(例如,它没有出现在 dba_tab_columns
中),因此它不包含在%rowtype
。 PL/SQL 记录 - 这是您正在构建的 PL/SQL table - 没有物理存储,因此没有真实或伪 rowid。
如果您真的想将行 ID 存储在 record/table 中,您必须显式声明类型:
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;
...
而且它可能也会使填充集合变得更加尴尬。因为无论如何您都必须知道所有 column/field 名称才能在循环中引用它们,所以我不确定这有什么好处,但您可能会发现它更简洁。
当然,这样做完全假设您的集合是从同一数据库甚至会话中 table 的数据子集填充的,因为一行的 rowid
会随时间变化.您可能还想查看 forall
语法来替换 for
循环,具体取决于您的实际操作。 (但是你也应该考虑你是否需要这个集合 - 如果你只是填充集合然后使用它进行更新那么单个 SQL 更新会更快......)