如何用 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 中的记录项初始化数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何用js push() 初始化一个二维数组

如何用一行代码初始化字符串类型的数组?

如何用不同的默认值初始化多维数组

如何用数字初始化 char 类型的全局一维数组?

如何用空值初始化这种形式的数组? (Java)[重复]

如何用数组初始化 glm::mat4?