关联数组是一组无界的键值对。每个键都是唯一的,作为保存有相应数据的元素的下标。因此您可以访问元素而不用知道它们在数组中的位置以及不用遍历整个数组。

键的数据类型可以是 PLS_INTEGER 或 VARCHAR2 (长度)。

  • 如果键的数据类型是 PLS_INTEGER,关联数组是按整数索引(indexed by integer)并且是密集型(指元素之间没有空隙),则从第一个元素到最后一个元素之间的每个元素都是有定义的,并且有值(值可以是 NULL )。

  • 如果键的数据类型是 VARCHAR2(长度),关联数组是按字符串索引(indexed by string)并且是稀疏型(指元素之间可能有空隙)。

当遍历密集的关联数组时,不需要考虑元素之间的空隙;当遍历稀疏的关联数组时,需要留意空隙。

给一个关联数组元素赋值,可以使用赋值表达式:

  1. array_name(key) := value

如果键不在数组中,这个赋值语句就会向数组中添加一个键值对;否则,赋值语句就修改了该键对应的值为新的值。

关联数组在临时存储数据时非常有用,它们不需要像表一样占用空间或网络资源,但是因为关联数组只是为了临时存储,不可以通过 DML 语句进行操作。

如果在包里面定义关联数组变量,在包体里面给它赋值,则关联数组在数据库会话期间都保持可见;否则,它只在所在的子程序范围内可见。

声明关联数组

要声明关联数组,需要先声明一个关联数组类型,然后声明这个类型的一个变量。最简单的语法格式如下:

  1. TYPE array_type IS TABLE OF element_type INDEX BY key_type;
  2. array_name array_type;

示例:声明关联数组

  1. delimiter /
  2. DECLARE
  3. -- 声明关联数组,不带游标
  4. TYPE TYPE_WARE IS TABLE OF ware%ROWTYPE INDEX BY PLS_INTEGER ;
  5. wares TYPE_WARE;
  6. TYPE TYPE_WARE_NAME IS TABLE OF ware.w_name%TYPE INDEX BY ware.w_id%TYPE;
  7. ware_names TYPE_WARE_NAME;
  8. BEGIN
  9. NULL;
  10. END;
  11. /
  12. delimiter ;

填充关联数组

最有效的填充一个密集型关联数组的方式是使用 SELECT INTO 语句带上 BULK COLLECT INTO 子句。

注意

如果一个密集型关联数组要填充的内容非常多,以至于 SELECT 语句会返回一个很大的结果集导致内存放不下,那么不要使用 SELECT 语句。可以通过游标和 FETCH 语句带上 BULK COLLECT INTO 和 LIMIT 子句来填充。

填充一个稀疏型关联数组时不能使用 SELECT 语句,可以在 FOR LOOP 循环语句里使用赋值语句。

下面示例使用 SELECT 语句填充按整型索引的关联数组,然后使用 FOR LOOP 语句填充一个按字符串索引的稀疏型关联数组。

示例:填充关联数组

  1. BEGIN
  2. -- 填充关联数组
  3. SELECT "W_ID","W_YTD","W_TAX","W_NAME","W_STREET_1","W_STREET_2","W_CITY","W_STATE","W_ZIP"
  4. BULK COLLECT INTO tab_wares FROM ware;
  5. FOR i IN 1..tab_wares.COUNT LOOP
  6. tab_ware_cities( tab_wares(i).w_name ) := tab_wares(i).w_city ;
  7. END LOOP;
  8. END;
  9. /

遍历密集型关联数组

密集型关联数组(按整型索引)的元素之间没有空隙,每个位于第一个和最后一个元素之间的元素都有定义和值(这个值可以是 NULL),可以使用 FOR LOOP 语句遍历一个密集型关联数组。

下面示例使用 FOR LOOP 语句去打印关联数组的每个元素值。其中,FOR LOOP 语句的上限 tab _wares.COUNT 调用了集合的方法 COUNT 返回数组中元素数目。

示例:遍历密集型关联数组

  1. -- 遍历关联数组
  2. FOR i IN 1..tab_wares.COUNT LOOP
  3. dbms_output.put_line(
  4. rpad( tab_wares(i).w_id, 23)
  5. || rpad( tab_wares(i).w_name, 23)
  6. || rpad(tab_wares(i).w_city, 23 )
  7. );
  8. END LOOP;

结果输出:

  1. Query OK, 0 rows affected (0.12 sec)
  2. 2 L6xwRsbDk vlwzndw2FPrO
  3. 1 n1P4zYo8OH srRq15uvxe5

遍历稀疏型关联数组

稀疏型关联矩阵(按字符串索引)在元素之间可能存在空隙,需要使用 WHILE LOOP 语句结合集合的方法 FIRST 和 NEXT 来遍历稀疏型关联数组。示例如下:

  1. -- 在声明部分增加:
  2. i_name ware.w_name%TYPE;
  3. -- 在执行部分增加:
  4. i_name := tab_ware_cities.FIRST ;
  5. WHILE i_name IS NOT NULL LOOP
  6. dbms_output.put_line(rpad(i_name,12) || tab_ware_cities(i_name) );
  7. i_name := tab_ware_cities.NEXT(i_name);
  8. END LOOP;