如何用 pl/sql 中的记录项初始化数组?
Posted
技术标签:
【中文标题】如何用 pl/sql 中的记录项初始化数组?【英文标题】:How i can initialize a array with record items in pl/sql? 【发布时间】:2018-03-22 17:04:37 【问题描述】:我对 pl/sql 比较陌生,我正在尝试创建一个包含记录对象的列表,但我不知道如何为列表中的每个项目初始化记录项中的两个字段。例如:在程序“新项目”中我如何初始化示例(1)?使用 example(1).id_std := integer 和 example(1).procent := integer ?谢谢!
这就是我的代码的样子:
set serveroutput on;
CREATE OR REPLACE PACKAGE newExercise IS
TYPE item IS RECORD(
id_std INTEGER,
procent INTEGER
);
TYPE tabel IS VARRAY(5) OF item;
PROCEDURE newItem (example tabel);
example2 tabel := tabel();
end newExercise;
/
CREATE OR REPLACE PACKAGE BODY newExercise IS
PROCEDURE newItem (example tabel) IS
BEGIN
FOR i IN 1..example.LIMIT LOOP
DBMS_OUTPUT.PUT_LINE(example(i));
end loop;
end newItem;
end newExercise;
/
【问题讨论】:
【参考方案1】:记录类型用于存储查询结果。所以你可以这样做:
declare
recs newExercise.tabel;
begin
select level, level * 0.25
bulk collect into recs
from dual
connect by level <= 5;
newExercise.newItem (recs);
end;
/
请注意,VARRAY 不是用于此目的的合适集合类型,因为并不总是可以预测查询将返回多少行。最好用
TYPE tabel IS table OF item;
【讨论】:
【参考方案2】:当您引用记录时,您通常必须指定特定字段。这将使用计算值填充记录;为了能够做到这一点,我不得不在规范中将过程参数从默认的IN
方向更改为IN OUT
:
CREATE OR REPLACE PACKAGE newExercise IS
TYPE item IS RECORD(
id_std INTEGER,
procent INTEGER
);
TYPE tabel IS VARRAY(5) OF item;
PROCEDURE newItem (example IN OUT tabel);
-- ^^^^^^ make in/out to be updateable
-- example2 tabel := tabel(); -- not used
END newExercise;
/
在体内:
CREATE OR REPLACE PACKAGE BODY newExercise IS
PROCEDURE newItem (example IN OUT tabel) IS
-- ^^^^^^ make in/out to be updateable
BEGIN
FOR i IN 1..example.LIMIT LOOP
-- extend collection to create new record
example.extend();
-- assign values to record fields
example(i).id_std := i;
example(i).procent := 100 * (1/i);
END LOOP;
END newItem;
END newExercise;
/
LIMIT
定义为 5,但 varray 实例最初为空(来自 tabel()
)。对于人口,您可以从 1 循环到 5 的限制,但您必须 extend()
集合才能在该位置实际创建记录。默认情况下,创建记录时所有字段都设置为空。然后,您可以为每条记录的字段分配值。 (很明显,我只是编造了一些东西)。
然后您可以使用匿名块对其进行测试:
declare
example newExercise.tabel := newExercise.tabel();
begin
-- call procedure
newExercise.newItem(example);
-- display contents for debuggibg
FOR i IN 1..example.COUNT LOOP
DBMS_OUTPUT.PUT_LINE('Item ' || i
|| ' id_std: ' || example(i).id_std
-- ^^^^^^^ refer to field
|| ' procent: ' || example(i).procent);
-- ^^^^^^^ refer to field
END LOOP;
end;
/
Item 1 id_std: 1 procent: 100
Item 2 id_std: 2 procent: 50
Item 3 id_std: 3 procent: 33
Item 4 id_std: 4 procent: 25
Item 5 id_std: 5 procent: 20
PL/SQL procedure successfully completed.
我已将原始循环用于在该块中显示数组的内容,因为您通常不会将其作为过程的一部分。对于该循环,您仍然可以使用 LIMIT
,但如果过程没有完全填充它,COUNT
会更安全。
你也可以在循环之前扩展一次:
PROCEDURE newItem (example IN OUT tabel) IS
BEGIN
-- extend collection to create all new records
example.extend(example.LIMIT);
FOR i IN 1..example.LIMIT LOOP
example(i).id_std := i;
example(i).procent := 100 * (1/i);
END LOOP;
END newItem;
如果您已经知道要分配的值 - 而且它们不是来自表,在这种情况下您会使用 APC 的方法 - 您可以只分配给最后创建的记录;这是一个相当人为的例子:
PROCEDURE newItem (example IN OUT tabel) IS
BEGIN
example.extend(); -- first record
example(example.LAST).id_std := 1;
example(example.LAST).procent := 7;
example.extend(); -- second record, left with null fields
example.extend(); -- third record
example(example.LAST).id_std := 3;
example(example.LAST).procent := 21;
example.extend(); -- fourth record, left with null fields
END newItem;
同样的匿名块现在给出:
Item 1 id_std: 1 procent: 7
Item 2 id_std: procent:
Item 3 id_std: 3 procent: 21
Item 4 id_std: procent:
PL/SQL procedure successfully completed.
注意空值,并且没有第 5 行。
或者再次扩展集合一次,直接引用编号记录:
PROCEDURE newItem (example IN OUT tabel) IS
BEGIN
example.extend(4);
example(1).id_std := 1;
example(1).procent := 7;
example(3).id_std := 3;
example(3).procent := 21;
END newItem;
从匿名块中得到相同的结果。
【讨论】:
以上是关于如何用 pl/sql 中的记录项初始化数组?的主要内容,如果未能解决你的问题,请参考以下文章