PL/SQL集合 - PL/SQL教程

集合是一个有序组具有相同的数据类型的元素。每个元素进行标识的唯一标表示其在集合中的位置。

PL/SQL提供了三种集合类型:

  • 索引表或关联数组

  • 嵌套表

  • 可变大小的数组或变长数组

Oracle文档提供了每种类型的集合的以下特征:

集合类型 元素数量 下标类型 密集或稀疏 在哪里创建 可以是对象类型属性
关联数组(或索引表) 无界 字符串或整数 两种都可以 只有在PL/SQL块 No
嵌套表 无界 整数 开始密集,可以变得稀疏 无论是在PL/SQL块或模式级别 Yes
可变大小的数组(变长数组) 有界 整数 总是密集 无论是在PL/SQL块或模式级别 Yes

我们已经在前讨论变长数组参见'PL/SQL数组“。在本章中将讨论PL/SQL表。

这两种类型的PL/SQL表即,索引表和嵌套表,都具有相同的结构以及行使用下标符号访问。然而,这两种类型的表有不同一个方面:嵌套表可以存储在数据库中的列,但索引表不能。

索引表

一个索引表(也叫关联数组)是一组键 - 值对。每个键是唯一的,并且用于定位对应的值。键可以是整数或字符串。

使用以下语法创建一个索引表。在这里,我们正在创建一个索引表命名表名,它的键是subscript_type类型以及对应值为 element_type 类型

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY subscript_type;

table_name type_name;

例子:

下面的示例演示如何创建一个表来存储整数值和键名称,它打印的名称相同的列表。

DECLARE
   TYPE salary IS TABLE OF NUMBER INDEX BY VARCHAR2(20);
   salary_list salary;
   name   VARCHAR2(20);
BEGIN
   -- adding elements to the table
   salary_list('Rajnish')  := 62000;
   salary_list('Minakshi')  := 75000;
   salary_list('Martin') := 100000;
   salary_list('James') := 78000;

   -- printing the table
   name := salary_list.FIRST;
   WHILE name IS NOT null LOOP
      dbms_output.put_line
      ('Salary of ' || name || ' is ' || TO_CHAR(salary_list(name)));
      name := salary_list.NEXT(name);
   END LOOP;
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Salary of Rajnish is 62000
Salary of Minakshi is 75000
Salary of Martin is 100000
Salary of James is 78000

PL/SQL procedure successfully completed.

例子:

一个索引表的元素也可以是任何数据库表字段%TYPE或任何数据库表%ROWTYPE。下面的例子说明了这个概念。我们将使用存储在数据库中CUSTOMERS表:

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      select  name from customers;

   TYPE c_list IS TABLE of customers.name%type INDEX BY binary_integer;
   name_list c_list;
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list(counter)  := n.name;
      dbms_output.put_line('Customer('||counter|| '):'||name_list(counter));
  END LOOP;
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik    
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed

嵌套表

嵌套表是就像一个一维数组的元素的数量。然而,嵌套表不同于在以下几方面的数组:

  • 数组具有元素的声明的数量,但嵌套表不用声明大小。嵌套表的大小可以动态地增加。

  • 数组总是密集的,也就是说,它总是有连续的下标。嵌套数组初始是致密,但是删除它的元素时就会变成稀疏。

使用以下语法创建一个嵌套表:

TYPE type_name IS TABLE OF element_type [NOT NULL];

table_name type_name;

这个声明是类似声明的索引表中,但没有INDEX BY子句。

嵌套表可以被存储在数据库中的列,所以它可用于简化在那里加入一个较大的表中的单个列,使用SQL操作。关联数组不能存储在数据库中。

例子:

下面的例子说明使用嵌套表:

DECLARE
   TYPE names_table IS TABLE OF VARCHAR2(10);
   TYPE grades IS TABLE OF INTEGER;

   names names_table;
   marks grades;
   total integer;
BEGIN
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');
   marks:= grades(98, 97, 78, 87, 92);
   total := names.count;
   dbms_output.put_line('Total '|| total || ' Students');
   FOR i IN 1 .. total LOOP
      dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));
   end loop;
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Total 5 Students
Student:Kavita, Marks:98
Student:Pritam, Marks:97
Student:Ayan, Marks:78
Student:Rishav, Marks:87
Student:Aziz, Marks:92

PL/SQL procedure successfully completed.

例子:

嵌套表的元素也可以是任何数据库表字段%TYPE和任何数据库表或%ROWTYPE。下面的例子说明了这个概念。我们将使用存储在数据库中的CUSTOMERS表:

Select * from customers;

+----+----------+-----+-----------+----------+
| ID | NAME     | AGE | ADDRESS   | SALARY   |
+----+----------+-----+-----------+----------+
|  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |
|  2 | Khilan   |  25 | Delhi     |  1500.00 |
|  3 | kaushik  |  23 | Kota      |  2000.00 |
|  4 | Chaitali |  25 | Mumbai    |  6500.00 |
|  5 | Hardik   |  27 | Bhopal    |  8500.00 |
|  6 | Komal    |  22 | MP        |  4500.00 |
+----+----------+-----+-----------+----------+
DECLARE
   CURSOR c_customers is
      SELECT  name FROM customers;

   TYPE c_list IS TABLE of customers.name%type;
   name_list c_list := c_list();
   counter integer :=0;
BEGIN
   FOR n IN c_customers LOOP
      counter := counter +1;
      name_list.extend;
      name_list(counter)  := n.name;
      dbms_output.put_line('Customer('||counter||'):'||name_list(counter));
   END LOOP;
END;
/

当上述代码在SQL提示符执行时,它产生了以下结果:

Customer(1): Ramesh
Customer(2): Khilan
Customer(3): kaushik    
Customer(4): Chaitali
Customer(5): Hardik
Customer(6): Komal

PL/SQL procedure successfully completed.

集合方法

PL/SQL提供,使集合更容易使用内置集合方法。下表列出了这些方法和用途:

S.N. 方法名称及用途
1 EXISTS(n) 返回TRUE,如果一个集合中的第n个元素的存在;否则返回FALSE
2 COUNT 返回集合当前包含的元素数量
3 LIMIT 检查集合的最大尺寸
4 FIRST 返回在使用整数下标集合的第一个(最小的)索引号
5 LAST 返回在使用整数下标集合的最后一个(最大的)索引号
6 PRIOR(n) 返回集合中索引n前面的索引号
7 NEXT(n) 返回索引n的下一个索引号
8 EXTEND 追加1个空元素到集合
9 EXTEND(n) 追加n个空元素到集合
10 EXTEND(n,i) 追加的第i个元素的集合的n个拷贝
11 TRIM 移除集合的末尾一个元素
12 TRIM(n) 移除一个集合末尾的n个元素
13 DELETE 移除一个集合中的所有元素,设置计数为0
14 DELETE(n) 移除关联数组用数字键或嵌套表中的第n个元素。如果关联数组有一个字符串键,对应于该键的值的元素将被删除。如果n为空,DELETE(N)什么都不做
15 DELETE(m,n) 移除关联数组或嵌套表范围m..n所有元素。如果m大于n或如果m大于或n是零,DELETE(M,N)什么也不做

集合异常

下表提供了集合异常和引发,当它们:

集合异常 引发情况
COLLECTION_IS_NULL 尝试在一个原子空(null)的集合操作
NO_DATA_FOUND 下标指定被删除的元素,或关联数组的一个不存在的元素
SUBSCRIPT_BEYOND_COUNT 下标超过了一个集合的元素数
SUBSCRIPT_OUTSIDE_LIMIT 下标超出了允许的范围
VALUE_ERROR 下标为空(null)或不可转换的键类型。如果该键被定义为PLS_INTEGER范围,下标是在该范围之外可能会出现这样的异常