存储子程序和包之使用关联数组

关联数组是一种集合类型。
这部分包括:
■ 关于集合
■ 关于关联数组
■ 声明关联数组
■ 填充关联数组
■ 遍历密集型关联数组
■ 遍历稀疏型关联数组

See Also: 关于集合的更多信息:
■ Oracle Database Concepts
■ Oracle Database PL/SQL Language Reference

关于集合
集合是以指定地顺序存储相同类型元素的PL/SQL复合变量,类似于一维数组。
集合的内部组件称为元素。
每个元素都有唯一的下标来标识它在集合中的位置。
要访问集合元素,你可以使用下标符号

collection_name(element_subscript).

你可以对待集合元素,如标量变量。
你也可以通过整个集合作为子程序参数(如果发送子程序和接收子程序都不是独立的子程序)

集合方法是一个内置的PL / SQL子程序,它或者返回关于集合的信息或者对集合进行操作。
要调用集合方法,你可以使用点符号

collection_name.method_name. 

例如,

collection_name.COUNT

返回集合元素个数。

PL/SQL有三种集合类型:
■ 关联数组 (之前称为 “PL/SQL tables” or “index-by tables”)
■ 嵌套表
■ 变量数组 (数组)
本文档仅解释关联数组。

See Also:
■ Oracle Database PL/SQL Language Reference for more information about PL/SQL collection types
■ Oracle Database PL/SQL Language Reference for more information about collection methods

关于关联数组
关联数组是一组无限的键/值对。
每个键都是唯一的,并作为保存对应值元素的下标。
因此,你可以访问元素而不需要知道它们在数组中的位置,并且不需要遍历数组。

键的数据类型可以是PLS_INTEGER,也可以是VARCHAR2 (length)

如果键的数据类型是PLS_INTEGER,则关联数组通过整数索引,并且是密集的(换言之,元素之间没有差距。),那么第一个和最后一个元素之间的每个元素都被定义并且具有一个值(可以为null)。

如果键的类型是VARCHAR2 (length),关联数组通过字符串(长度字符)索引并且是稀疏的;换言之,在元素之间可能有差距。

当遍历一个密集的关联数组,你不需要注意元素之间的差距;当遍历一个稀疏的关联数组,你需要。

要将值分配给关联数组元素,可以使用赋值运算符:

array_name(key) := value

If key is not in the array, then the assignment statement adds the key-value pair to the array.
Otherwise, the statement changes the value of to value.
如果键不在数组内,则赋值语句在数组中添加该键/值对。
否则,该赋值语句修改array_name(key)value

关联数组对于存储临时数据是有用的。
它们不使用表所需的磁盘空间或网络操作。
然而,因为关联数组是用于临时存储,你不能使用DML语句操纵它们。

假如你声明在包中声明了关联数组,并且在包体中赋值给该变量,则该关联数组存在于数据库会话的生命周期。
否则,它存在于声明它的子程序的生命周期。

See Also: Oracle Database PL/SQL Language Reference for more information about associative arrays

声明关联数组
要声明关联数组,你可以先声明关联数组类型,然后声明该类型的变量。
最简单的语法:

TYPE array_type IS TABLE OF element_type INDEX BY key_type;
array_name array_type;

声明关联数组的一个有效方式是使用游标,使用下面的过程。
该过程使用最简单形式的每个必要的语句,但是提高参考它的完整语法。

使用游标来声明一个关联数组:
1. 声明部分:
a. 声明游标:

CURSOR cursor_name IS query;

For complete declared cursor declaration syntax, see Oracle Database PL/SQL Language Reference.

b. 声明关联数组类型:

TYPE array_type IS TABLE OF cursor_name%ROWTYPE
INDEX BY { PLS_INTEGER | VARCHAR2 length }

For complete associative array type declaration syntax, see Oracle Database PL/SQL Language Reference.

c. 声明该类型的关联数组变量:

array_name array_type;

For complete variable declaration syntax, see Oracle Database PL/SQL Language Reference.

Example 5–9 使用上述过程来声明两个关联数组,employees_jobsjobs_,之后声明了第三个关联数组,job_titles,没有使用游标。
前两个数组通过整数索引,第三个通过字符串索引。

Note:employees_jobs_cursor声明中的ORDER BY子句决定关联数组employee_jobs元素的存储顺序。

Example 5–9 声明关联数组:

DECLARE
  -- Declare cursor:
  CURSOR employees_jobs_cursor IS
    SELECT FIRST_NAME, LAST_NAME, JOB_ID
      FROM EMPLOYEES
     ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;
  -- Declare associative array type:
  TYPE employees_jobs_type IS TABLE OF employees_jobs_cursor%ROWTYPE INDEX BY PLS_INTEGER;
  -- Declare associative array:
  employees_jobs employees_jobs_type;
  -- Use same procedure to declare another associative array:
  CURSOR jobs_cursor IS
    SELECT JOB_ID, JOB_TITLE FROM JOBS;
  TYPE jobs_type IS TABLE OF jobs_cursor%ROWTYPE INDEX BY PLS_INTEGER;
  jobs_ jobs_type;
  -- Declare associative array without using cursor:
  TYPE job_titles_type IS TABLE OF JOBS.JOB_TITLE%TYPE INDEX BY JOBS.JOB_ID%TYPE; -- jobs.job_id%type is varchar2(10)
  job_titles job_titles_type;
BEGIN
  NULL;
END;

See Also:
■ “About Cursors” on page 5-31
■ Oracle Database PL/SQL Language Reference for associative array declaration syntax

填充关联数组
The most efficient way to populate a dense associative array is usually with a SELECT statement with a BULK COLLECT INTO clause.
填充密集的关联数组最有效的方式通常是使用SELECT语句和BULK COLLECT INTO子句。

Note: 如果一个密集的关联数组是如此之大,以至于一个SELECT语句返回的结果集太大,不适合在内存中,则不要使用SELECT语句。
相反,使用游标和FETCH语句和BULK COLLECT INTOLIMIT子句来填充数组。

For information about using the FETCH statement with BULK COLLECT clause, see Oracle Database PL/SQL Language Reference.

你不能使用SELECT语句来填充稀疏的关联数组(such as job_titles in “Declaring Associative Arrays” on page 5-40)。
相反,你必须使用循环语句中的赋值语句。

For information about loop statements, see “Controlling Program Flow” on page 5-20.

Example 5–10使用SELECT语句来填充关联数组employees_jobsjobs_,通过整数索引。
然后使用在FOR LOOP语句中的赋值语句来填充关联数组job_titles,通过字符串索引。

Example 5–10 填充关联数组

BEGIN
  -- Populate associative arrays indexed by integer:
  SELECT FIRST_NAME, LAST_NAME, JOB_ID
    BULK COLLECT
    INTO employees_jobs
    FROM EMPLOYEES
   ORDER BY JOB_ID, LAST_NAME, FIRST_NAME;
  SELECT JOB_ID, JOB_TITLE BULK COLLECT INTO jobs_ FROM JOBS;
  -- Populate associative array indexed by string:
  FOR i IN 1 .. jobs_.COUNT() LOOP
    job_titles(jobs_(i).job_id) := jobs_(i).job_title;
  END LOOP;
END;
/

See Also: “About Cursors” on page 5-31

遍历密集的关联数组
密集的关联数组(整数索引)在元素之间没有间隔—第一个和最后一个元素之间的每个元素都被定义并且具有一个值(可以是NULL)。
你可以使用FOR LOOP语句来遍历一个密集的关联数组,Example 5–11

当插入到示例5-10的可执行部分中时,在填充employees_jobs数组的代码之后,示例5-11中的FOR LOOP语句将打印employees_jobs数组的元素按存储顺序排列。
他们的存储顺序是由employees_jobs_cursor声明中的ORDER BY子句决定的,用于声明employees_jobs(见例5-9)。

FOR LOOP语句的上限,employees_jobs
COUNT,调用一个返回数组中元素数量的集合方法。
For more information about COUNT, see Oracle Database PL/SQL Language Reference.

Example 5–11 遍历密集的关联数组

-- Code that populates employees_jobs must precede this code:
FOR i IN 1..employees_jobs.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(
RPAD(employees_jobs(i).first_name, 23) ||
RPAD(employees_jobs(i).last_name, 28) || employees_jobs(i).job_id);
END LOOP;

遍历稀疏的关联数组
A sparse associative array (indexed by string) might have gaps between elements.
稀疏的关联数组(字符串索引)可能在元素之间有间隔。
你可以使用WHILE LOOP语句来遍历它,Example 5–12

要运行示例5-12中的代码,该代码打印job_titles数组的元素:
1. 在示例5-9的声明部分的末尾,插入以下变量声明:

i jobs.job_id%TYPE;

2.示例5-10的可执行部分中,填充job_titles数组的代码之后,插入示例5-12中的代码。

Example 5–12 包含两个集合方法的调用, job_titles.FIRST 和job_titles.NEXT(i)。
job_titles.FIRST 返回job_titles的第一个元素,job_titles.NEXT(i)返回成功的下标i。
For more information about FIRST, see Oracle Database PL/SQL Language Reference.
For more information about NEXT, see Oracle Database PL/SQL Language Reference

Example 5–12 遍历稀疏的关联数组

/* Declare this variable in declarative part:
i jobs.job_id%TYPE;
Add this code to the executable part,
after code that populates job_titles:
*/
i := job_titles.FIRST;
WHILE i IS NOT NULL LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(i, 12) || job_titles(i));
i := job_titles.NEXT(i);
END LOOP;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值