我如何用pl / sql中的记录项初始化数组?

时间:2018-03-22 17:04:38

标签: database oracle plsql

我对pl / sql比较新,我试图用记录对象创建一个列表,但我不知道如何为记录项中的两个字段初始化列表的每个项目。例如:在程序"新项目"我怎么能初始化例子(1)? with 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;
/

2 个答案:

答案 0 :(得分:3)

记录类型用于存储查询结果。所以你可以这样做:

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;

答案 1 :(得分:0)

当您参考记录时,您通常必须指定特定字段。这将使用计算值填充记录;为了能够做到这一点,我必须在规范中将过程参数从默认的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()集合才能在该位置实际创建记录。默认情况下,创建记录时将所有字段设置为null。然后,您可以将值分配给每个记录的字段。 (显然我已经做了一些事情)。

然后,您可以使用匿名块进行测试:

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;

从匿名块获得相同的结果。