【问题标题】:How i can initialize a array with record items in pl/sql?如何用 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;
/

【问题讨论】:

    标签: database oracle plsql


    【解决方案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;
      

      从匿名块中得到相同的结果。

      【讨论】:

        猜你喜欢
        • 2011-12-23
        • 2011-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        相关资源
        最近更新 更多