collection_name collection_type [:=collection_type(...)];
其中,collection_name是集合变量的名字,collection_type具有两层含义,它即代表着一个先前已经声明的集合类型的名字,同时也代表着(如果是嵌套表或者VARRAY的话)和该类型同名的构造函数。
构造函数的名字和类型的名字是相同的,并且接收一个用逗号分隔的元素列表作为参数。如果我们声明的是一个嵌套表或者VARRAY变量,我们在使用之前必须要先对这个变量进行初始化。
3.2集合变量的初始化
对于嵌套表类型集合变量和VARRAY类型集合变量,在使用集合变量之前必须要进行初始化,而对于关联数组类型不需要初始化。下面主要讨论嵌套表和VARRY的初始化。
3.2.1通过构造函数的显示初始化
通过构造函数显示地给集合变量初始。例如:
declare
vnt_employee nt_employee :=nt_employee(); --不带参数的构造函数初始化
vnt_employee nt_employee :=nt_employee('张三','李四','王五'); --带参数的构造函数初始化
begin
null;
end;
3.2.2直接赋值时的隐式初始化
如果两个集合实例是基于同一集合类型,我们可以把其中一个实例的全部内容拷贝给另一个,这就相当于进行了初始化。例如:
declare
vnt_employee nt_employee :=nt_employee('James','Lucy','Jordan');
vnt_foregin_employee nt_employee;
begin
vnt_foregin_employee := vnt_employee;
end;
3.2.3通过FETCH操作的隐式初始化
在使用FETCH或者 SELECT INTO语句从数据库提取提取一个集合并保存到一个集合变量时,集合变量会自动初始化,就像直接赋值一样。
declare
vnt_colors nt_color;
begin
select colors into vnt_colors from color_models; --表color_models的color列是嵌套表类型。
end;
3.2.4通过BULK COLLECT语句的隐式初始
使用BULK COLLECT INTO语句批量提取数据并保存到一个集合变量,集合变量会自动初始化,就像直接赋值一样。
declare
vnt_employee nt_employee; --未初始化
begin
select e.ename bulk collect intovnt_employee from emp e;
end;
declare
cursor cur_employee is select e.ename from emp e;
vnt_employee nt_employee; --未初始化
begin
open cur_employee;
fetch cur_employee bulk collect into vnt_employee;
close cur_employee;
end;
4.集合方法
Oracle提供了提供许多内置的函数和过程可以用于获取集合的信息或者修改集合的内容,这些方法也叫做集合方法。下面给出这些方法的完整列表:
| 方法(函数或者过程) |
说 明 |
| COUNT函数 |
返回集合中现有元素的数量 |
| DELETE过程 |
从集合中移除一个或者多个元素。如果不是重复移除,会减少COUNT的值,对于VARRAY,你只能删除集合的所有元素 |
| EXISTS函数 |
根据某个指定的元素是否已经在集合中,返回TURE或者FALES |
| EXTEND过程 |
增加嵌套表或者VARRAY中元素的个数,同时增加COUNT的值 |
| FIRST、LAST函数 |
返回可用的最小(FIRST)和最大(LAST)集合下标 |
| LIMIT函数 |
返回VARRAY中允许ude最大元素数量 |
| PRIOD、NEXT函数 |
返回紧挨着指定的下标之前(PRIOD)或者之后(NEXT)的下标值。你应该总是用PRIOD和NEXT在集合内遍历,尤其在使用稀疏(或者可能是稀疏)集合时更是如此 |
| TRIM过程 |
从集合的尾部(定义的最大下标)移除集合元素 |
之所以把这些过程叫做方法,是因为使用这些集合内置程序的语法不同于调用过程和函数的正规语法。
5.集合类型对比
Oracle 集合类型对比
| 属 性 |
关 联 数 组 |
嵌 套 表 |
可变长数组 |
| 维度 |
一维 |
一维 |
一维 |
| 是否可用于SQL |
不可用 |
可用 |
可用 |
| 是否可作为表中列的数据类型 |
不可用 |
可以;数据是在“行外”保存的(一个独立的表) |
可以;数据保存在“行内”(在同一个表中) |
| 未初始化时的状态 |
空(不能是NULL);元素是为定义 |
自动就是NULL的;对元素的引用是非法的 |
自动就是NULL;对元素的引用是非法的 |
| 初始化 |
在声明时自动完成 |
通过构造函数,或者赋值,或者fetch操作完成 |
通过构造函数,或者赋值,或者fetch操作完成 |
| 在PL/SQL中元素的引用方式 |
BINARY_INTEGER以及其子类型 |
VARCHAR2(Oracle 9i数据库R2版本或者更高版本) |
1到2 147 483 647间的整数 |
| 是否稀疏 |
是 |
开始不是;经过删除后就成稀疏了 |
不是 |
| 是否有界 |
无界 |
可以扩展 |
有界 |
| 可以随时对任意一个元素赋值 |
可以 |
不可以,可以需要用EXTEND进行扩展 |
不可以;可以用EXTEND进行扩展,而且扩展时不能超出上边界 |
| 扩展的方法 |
给一个新下标指向的元素赋值 |
使用内置的EXTEND过程(或者TRIM进行压缩),没有预定义的最大值 |
使用内置EXTEND过程(或者TRIM进行压缩),但是最大只能到声明的最大尺寸 |
| 可以比较相等与否 |
不可以 |
可以,要求是Oracle 10g或者以后的版本 |
不可以 |
| 是否可以通过集合操作符进行操作 |
不可以 |
可以,要求是Oracle 10g或者以后的版本 |
不可以 |
| 存取数据时是否会保留顺序或者下标 |
N/A |
不保留 |
保留 |
6.集合示例
6.1关联数组示例
declare
type nt_foregn_employee is table of varchar2(30) index by binary_integer;
vnt_foregn_employees nt_foregn_employee;
v_row number;
begin
vnt_foregn_employees(-230002) := 'SCOTT';
vnt_foregn_employees(-23) := 'JONES';
vnt_foregn_employees(1) := 'ALLEN';
vnt_foregn_employees(5934) := 'CLARK';
vnt_foregn_employees(13342) := 'ADAMS';
vnt_foregn_employees(8234223) := 'KING';
--使用FIRST方法获取集合中的一个行号
v_row := vnt_foregn_employees.first;
while (v_row is not null) loop
dbm