如何用PLSQL访问两级都使用varchar2做索引的关联数组?

问题描述 投票:0回答:1

我试图访问一个只用varchar2做索引的嵌套关联数组的第二层,但我遇到了一个问题。 我在网上找到的每个例子都在某个地方使用整数作为索引,这对我没有帮助。

下面是一些示例代码。


DECLARE

    l_idx1 VARCHAR(50);
    l_idx2 VARCHAR(50);

    TYPE counter_type IS RECORD (
        updated INTEGER,
        inserted INTEGER,
        deleted INTEGER
    );

    TYPE counter_tab IS TABLE OF counter_type INDEX BY VARCHAR2(50);

    counters counter_tab;

BEGIN

    counters('example_table1').updated := 0;
    counters('example_table1').inserted := 0;
    counters('example_table1').deleted := 0;

    counters('example_table2').updated := 0;
    counters('example_table2').inserted := 0;
    counters('example_table2').deleted := 0;

    counters('example_table3').updated := 0;
    counters('example_table3').inserted := 0;
    counters('example_table3').deleted := 0;

    counters('example_table3').inserted := counters('example_table3').inserted + 12;
    counters('example_table2').updated := counters('example_table2').updated + 32;

    DBMS_OUTPUT.PUT_LINE('foo: ' || counters('example_table2').updated); -- testing this out


    l_idx1 := counters.FIRST;
    WHILE l_idx1 IS NOT NULL
    LOOP
        DBMS_OUTPUT.PUT_LINE('idx: ' || l_idx1);
        l_idx2 := counters(l_idx1).FIRST;  - This is where the problem is!!
        WHILE l_idx2 IS NOT NULL
        LOOP
            DBMS_OUTPUT.PUT_LINE('Table: ' || l_idx1 || 'Counter: ' || counters(l_idx1).l_idx2);
            IF counters(l_idx1).l_idx2 > 0
            THEN
                DBMS_OUTPUT.PUT_LINE('Records ' || l_idx2 || ' for table ' || l_idx1 || ': ' || counters(l_idx1).l_idx2); 
            END IF;

            l_idx2 := counters(l_ldx1).NEXT(l_idx2);  --  Like another problem!
        END LOOP;
        l_idx1 := counters.NEXT(l_idx1);
    END LOOP;

END;
/

所以,我想做的是循环检查第一层的关联数组 对每一个数组都循环检查第二层数组并打印出数值 看起来好像很简单,而且可能是这样的。 :-)

谢谢你的帮助!

lkl

oracle plsql nested associative-array
1个回答
0
投票

你只有一层数组(counter_tab)类型的 counter_type.

你可以通过循环 counters 但是计数器里面没有数组,所以这是不可能的。

用下面的代码,万一对你有帮助呢。

SQL> DECLARE
  2  L_IDX1     VARCHAR(50);
  3  L_IDX2     VARCHAR(50);
  4  TYPE COUNTER_TYPE IS RECORD (
  5  UPDATED    INTEGER,
  6  INSERTED   INTEGER,
  7  DELETED    INTEGER
  8  );
  9  TYPE COUNTER_TAB IS
 10  TABLE OF COUNTER_TYPE INDEX BY VARCHAR2(50);
 11  COUNTERS   COUNTER_TAB;
 12  BEGIN
 13  COUNTERS('example_table1').UPDATED    := 0;
 14  COUNTERS('example_table1').INSERTED   := 0;
 15  COUNTERS('example_table1').DELETED    := 0;
 16  COUNTERS('example_table2').UPDATED    := 0;
 17  COUNTERS('example_table2').INSERTED   := 0;
 18  COUNTERS('example_table2').DELETED    := 0;
 19  COUNTERS('example_table3').UPDATED    := 0;
 20  COUNTERS('example_table3').INSERTED   := 0;
 21  COUNTERS('example_table3').DELETED    := 0;
 22  COUNTERS('example_table3').INSERTED   := COUNTERS('example_table3').INSERTED + 12;
 23  COUNTERS('example_table2').UPDATED    := COUNTERS('example_table2').UPDATED + 32;
 24  DBMS_OUTPUT.PUT_LINE('foo: ' || COUNTERS('example_table2').UPDATED); -- testing this out
 25  L_IDX1                                := COUNTERS.FIRST;
 26  WHILE L_IDX1 IS NOT NULL LOOP
 27  DBMS_OUTPUT.PUT_LINE('idx: ' || L_IDX1);
 28  DBMS_OUTPUT.PUT_LINE('updated: ' || COUNTERS(L_IDX1).UPDATED);
 29  DBMS_OUTPUT.PUT_LINE('inserted: ' || COUNTERS(L_IDX1).INSERTED);
 30  DBMS_OUTPUT.PUT_LINE('deleted: ' || COUNTERS(L_IDX1).DELETED);
 31  L_IDX1 := COUNTERS.NEXT(L_IDX1);
 32  END LOOP;
 33
 34  END;
 35  /
foo: 32
idx: example_table1
updated: 0
inserted: 0
deleted: 0
idx: example_table2
updated: 32
inserted: 0
deleted: 0
idx: example_table3
updated: 0
inserted: 12
deleted: 0

PL/SQL procedure successfully completed.

SQL>

0
投票

你可以做你要找的事,只是你如何去做,就会有很大的不同。首先让我们澄清一下你对什么需要索引(下标)和如何引用Record的误解。当你定义一个类型的Record时,你并不是通过索引来访问它,(正如其他人所指出的)你可以 只按名称访问记录属性. 以这种方式,记录的引用和表的引用是一样的,当引用一个表的列时,你使用的语法是TABLE_NAME.COLUMN_NAME,同样的,记录的属性引用是RECORD_NAME.ATTRIBUTE_NAME。当引用一个表列时,你使用语法TABLE_NAME.COLUMN_NAME同样引用一个记录属性为RECORD_NAME.ATTRIBUTE_NAME。 唯一被索引引用的plsql对象是一个集合(嵌套表、关联数组、varray)。所以要想得到你想要的东西,你需要声明一个 荟萃 而不是一个记录的集合。在这种情况下,一个整数的关联数组的关联数组。进一步的索引方式,每个索引都用括号括起来,与其他(s)分开,所以C(i1)(i2)而不是C(i1,i2)。你还必须记住你要引用的是什么级别,因为集合属性(first, last, next, ...)等都是独立的索引(算是吧)。但是如果你能把所有的事情都弄清楚,那么级别的数量是没有限制的(AFAIK)。 下面展示了如何去做你想要的事情。它值得努力吗?在这种情况下,可能不值得,除非你的全部问题需要在事先不知道索引值的情况下引用(在这种情况下,你需要防范NO_DATA_FOUND异常),或者你需要在飞行中添加索引值。只有你能决定。

declare
  l_idx1     varchar(50);       -- 1st level index
  l_idx2     varchar(8);        -- 2nd level index

  -- 2nd level collection. Defines a collection of integers
  type counter_type is  
       table of integer
       index by varchar2(8) ;           

  -- 1st level collection.  Defines a collection of a collection of integers
  type counter_tab is
       table of counter_type 
       index by varchar2(50);

  -- variable for collection of a collection of integers
  counters   counter_tab;

begin
  -- initialize counters
  counters('example_table1')('updated')    := 0;
  counters('example_table1')('inserted')   := 0;
  counters('example_table1')('deleted')    := 0;

  counters('example_table2')('updated')    := 0;
  counters('example_table2')('inserted')   := 0;
  counters('example_table2')('deleted')    := 0;

  counters('example_table3')('updated')    := 0;
  counters('example_table3')('inserted')   := 0;
  counters('example_table3')('deleted')    := 0;

  -- perform some operations  
  counters('example_table3')('inserted')   := counters('example_table3')('inserted') + 12;
  counters('example_table2')('updated')    := counters('example_table2')('updated') + 32;

  -- loop through results 
  l_idx1 := counters.first;
  while l_idx1 is not null 
  loop
      dbms_output.put_line('Outer index: ' || l_idx1);
      l_idx2 := counters(l_idx1).first ; 
      while l_idx2 is not null 
      loop 
          dbms_output.put_line('   ''' || l_idx2 || ':'' '  || to_char(counters(l_idx1)(l_idx2)));
          l_idx2 := counters(l_idx1).next(l_idx2);
     end loop; 
  l_idx1 := counters.next(l_idx1);
  end loop;

end;
© www.soinside.com 2019 - 2024. All rights reserved.