#集合变量

YashanDB包含如下三种集合变量:

  • 可变长数组(VARRAY):一个可变长数组包含一组相同类型的成员,成员在数组内有序存放。
  • 嵌套表(NESTED TABLE):一个嵌套表包含多行相同类型的成员,类似于物理表记录存储,行成员在嵌套表中无序存放。使用嵌套表可以更方便地实现多维数组的定义和操作。
  • 关联数组(INDEX-BY TABLE):一个关联数组包含多个键值对成员,每个键是一个唯一的索引,键值对成员按索引有序存放。
三者对比 VARRAY NESTED TABLE INDEX-BY TABLE
成员个数限制 在定义时必须声明其最大长度,实际长度(即成员个数)在此范围内动态改变 实际长度(即成员个数)可在资源允许范围内一直动态扩展 实际长度(即成员个数)可在资源允许范围内一直动态扩展
成员存放方式 成员有序存放 行成员无序存放 键值对成员按索引有序存放
成员数据类型 可以为除游标类型外的任何PL数据类型 可以为除游标类型外的任何PL数据类型 * 索引:可以为INTEGER、PLS_INTEGER、BINARY_INTEGER、VARCHAR类型
* 值:可以为除游标类型外的任何PL数据类型
定义方式 * 可在过程体内部定义
* 可作为UDT在过程体外部定义
* 可在过程体内部定义
* 可作为UDT在过程体外部定义
仅支持在过程体内部定义
其他 - - 对于关联数组而言,声明即初始化

# 集合变量声明

声明集合变量前需进行集合类型的定义,在过程体内部定义集合变量的语法为:

varray_definition
TYPE varray_type IS VARRAY VARYING ARRAY ( size_limit ) OF datatype NOT NULL
nested_table_definition
TYPE nested_table_type IS TABLE OF datatype NOT NULL
indexby_table_definition
TYPE indexby_table_type IS TABLE OF datatype NOT NULL INDEX BY index_datatype

对集合变量的声明语法为:

syntax
variable_name varray_type nested_table_type indexby_table_type ;

size_limit

在声明数组类型时,必须指定数组成员的个数上限,取值范围为[1,int32]。

datatype

成员的数据类型,可指定为PL支持的所有类型或UDT。当数据类型为字符型时,须同时指定其Size属性,例如VARCHAR(10),但输入CHAR默认等同于CHAR(1);可指定的最大Size为32000。

NOT NULL

使用NOT NULL指定集合的成员不能设置为NULL,省略时,默认集合中的成员可以设置为NULL。

index_datatype

索引的数据类型,可指定为INTEGER、PLS_INTEGER、BINARY_INTEGER或VARCHAR类型。当数据类型为字符型时,须同时指定其Size属性,例如VARCHAR(10);可指定的最大Size为32000。

# 集合变量赋值

集合变量赋值包括初始化赋值和过程中赋值。

  • 可以通过如下格式为集合成员赋值:

    variable_name := (varray_type|nested_table_type) (expr1,expr2,...);
    
    variable_name := indexby_table_type(key1=>value1,key2=>value2,...);
    
    variable_name(index) := expr;
    

    当成员类型为普通标量类型时,expr为一个YashanDB认可的通用表达式,否则为该成员类型所规定的赋值格式。

  • 可以将一个已初始化值的集合变量赋值给另一个集合变量。

  • 可以通过数组相关内置函数对数组进行赋值,例如STRING_TO_ARRAYARRAY_APPENDARRAY_REMOVEARRAY_REPLACE等。

# 集合变量访问

一个已被赋值的集合变量可以通过如下语法访问:

syntax
varray_type nested_table_type indexby_table_type ( expr )

expr为一个YashanDB认可的通用表达式,对于数组和嵌套表,其结果必须为一个数字,表示数组内索引,数组内索引以1为首位;对于关联数组,其结果的数据类型必须符合声明的索引数据类型,否则会进行隐式类型转换。

示例

CREATE OR REPLACE TYPE udt_object FORCE AS OBJECT (
	area_no CHAR(2),
    MAP MEMBER FUNCTION showArea RETURN VARCHAR
) NOT FINAL;
/
CREATE OR REPLACE TYPE BODY udt_object AS
	MAP MEMBER FUNCTION showArea RETURN VARCHAR AS
    BEGIN
		RETURN self.area_no;
	END;
END;
/ 

--通过VARRAY定义单维+嵌套数组并访问
DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	v_char1 char_array := char_array('1',TO_CHAR(2),'');
	v_char2 char_array := v_char1;
	TYPE array_array IS ARRAY(3) OF char_array;
	v_array array_array;
	TYPE udt_array IS ARRAY(3) OF udt_object;
	v_udt udt_array;
	TYPE rec IS RECORD(area udt_object, branch CHAR(4));
	TYPE rec_array IS ARRAY(3) OF rec;
	v_rec rec_array;
BEGIN
	DBMS_OUTPUT.PUT_LINE('char array:'||v_char2(1)||v_char2(TO_NUMBER('2'))||v_char2(3));
	v_array := array_array(v_char1,v_char2);
	DBMS_OUTPUT.PUT_LINE('array array:'||v_array(1)(1)||v_array(1)(2)||v_array(2)(1)||v_array(2)(2));
	v_udt := udt_array(udt_object('01'),udt_object('02'));
	DBMS_OUTPUT.PUT_LINE('udt array:'||v_udt(1).area_no||' '||v_udt(2).area_no);
	v_rec := rec_array(rec(udt_object('03'),'0301'),rec(udt_object('04'),'0401'));
	DBMS_OUTPUT.PUT_LINE('record array:'||v_rec(1).area.area_no||'.'||v_rec(1).branch||
    ' '||v_rec(2).area.area_no||'.'||v_rec(2).branch);
END;
/
--result
char array:12
array array:1212
udt array:01 02
record array:03.0301 04.0401  

--通过NESTED TABLE定义多维数组并访问
DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	v_table char_table;
BEGIN
	v_table := char_table(char_array('1',TO_CHAR(2),''),char_array('1',TO_CHAR(2),''));
	DBMS_OUTPUT.PUT_LINE('nested table: '||v_table(1)(1)||v_table(1)(2)||' '||v_table(2)(1)||v_table(2)(2));
END;
/
--result
nested table: 12 12

--通过INDEX-BY TABLE定义一个索引为VARCHAR类型的关联数组并访问
DECLARE
    TYPE char_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_table char_table;
BEGIN
    v_table('a') := 1;
	DBMS_OUTPUT.PUT_LINE('index-by table: '||v_table('a'));
END;
/
--result
index-by table: 1

# 集合变量操作方法

除上述通过索引直接访问集合成员的方法外,YashanDB还内置了一系列方法,用于在过程体内对集合变量执行指定的操作。

除EXISTS外,其他方法都必须在集合变量初始化后才可以操作。

# LIMIT

syntax
varray_type nested_table_type indexby_table_type . limit ()

LIMIT为一个函数,用于获得集合的成员数量上限,对于嵌套表和关联数组,函数返回NULL。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idx_table IS TABLE OF char_array INDEX BY INT;
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxt_char idx_table;
BEGIN
	DBMS_OUTPUT.PUT_LINE('array limit: '||v_char.LIMIT);
	DBMS_OUTPUT.PUT_LINE('nested table limit: '||v_t_char.LIMIT);
	DBMS_OUTPUT.PUT_LINE('index-by table limit: '||v_idxt_char.LIMIT);
END;
/

--result
array limit: 5
nested table limit: 
index-by table limit: 

# COUNT

syntax
varray_type nested_table_type indexby_table_type . count ()

COUNT为一个函数,用于获得集合当前存在的成员数量。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idx_table IS TABLE OF char_array INDEX BY INT;
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxt_char idx_table := idx_table(1=>v_char);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array count: '||v_char.count());
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_t_char.count());
	DBMS_OUTPUT.PUT_LINE('index-by table count: '||v_idxt_char.count());
END;
/

--result
array count: 3
nested table count: 3
index-by table count: 1

# FIRST

syntax
varray_type nested_table_type indexby_table_type . first ()

FIRST为一个函数,用于获得集合当前存在的第一个成员索引。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idx_table IS TABLE OF char_array INDEX BY INT;
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxt_char idx_table := idx_table(-10=>v_char, 100=>v_char);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array first: '||v_char.first());
	DBMS_OUTPUT.PUT_LINE('nested table first: '||v_t_char.first());
	DBMS_OUTPUT.PUT_LINE('index-by table first: '||v_idxt_char.first());
END;
/

--result
array first: 1
nested table first: 1
index-by table first: -10

# LAST

syntax
varray_type nested_table_type indexby_table_type . last ()

LAST为一个函数,用于获得集合当前存在的最后一个成员索引。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idx_table IS TABLE OF char_array INDEX BY INT;
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxt_char idx_table := idx_table(-10=>v_char, 100=>v_char);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array last: '||v_char.last());
	DBMS_OUTPUT.PUT_LINE('nested table last: '||v_t_char.last());
	DBMS_OUTPUT.PUT_LINE('index-by table last: '||v_idxt_char.last());
END;
/

--result
array last: 3
nested table last: 3
index-by table last: 100

# NEXT

syntax
varray_type nested_table_type indexby_table_type . next ( expr )

NEXT为一个函数,用于获得输入索引在集合内存在的下一个索引。输入的索引可以是不存在的索引,此时函数返回集合内最接近该索引的下一个索引。当输入的索引为NULL或不存在下一个索引时,函数返回NULL。

expr为一个YashanDB认可的通用表达式,其结果的数据类型必须符合集合的索引数据类型,否则会进行隐式类型转换。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idxby_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxtable idxby_table := idxby_table('b'=>1,'a'=>2,'e'=>3);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array next0: '||v_char.NEXT(0));
	DBMS_OUTPUT.PUT_LINE('array next-9: '||v_char.NEXT(-9));
	DBMS_OUTPUT.PUT_LINE('array next3: '||v_char.NEXT(3));
	DBMS_OUTPUT.PUT_LINE('nested table next0: '||v_t_char.NEXT(0));
	DBMS_OUTPUT.PUT_LINE('nested table next-9: '||v_t_char.NEXT(-9));
	DBMS_OUTPUT.PUT_LINE('nested table next3: '||v_t_char.NEXT(3));
	DBMS_OUTPUT.PUT_LINE('index-by table next b: '||v_idxtable.NEXT('b'));
END;
/

--result
array next0: 1
array next-9: 1
array next3: 
nested table next0: 1
nested table next-9: 1
nested table next3: 
index-by table next b: e

# PRIOR

syntax
varray_type nested_table_type indexby_table_type . prior ( expr )

PRIOR为一个函数,用于获得输入索引在集合内存在的上一个索引。输入的索引可以是不存在的索引,此时函数返回集合内最接近该索引的上一个索引。当输入的索引为NULL或不存在上一个索引时,函数返回NULL。

expr为一个YashanDB认可的通用表达式,其结果的数据类型必须符合集合的索引数据类型,否则会进行隐式类型转换。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idxby_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxtable idxby_table := idxby_table('b'=>1,'a'=>2,'e'=>3);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array prior-9: '||v_char.PRIOR(-9));
	DBMS_OUTPUT.PUT_LINE('array prior1: '||v_char.PRIOR(1));
	DBMS_OUTPUT.PUT_LINE('array prior4: '||v_char.PRIOR(4));
	DBMS_OUTPUT.PUT_LINE('nested table prior-9: '||v_t_char.PRIOR(-9));
	DBMS_OUTPUT.PUT_LINE('nested table prior1: '||v_t_char.PRIOR(1));
	DBMS_OUTPUT.PUT_LINE('nested table prior4: '||v_t_char.PRIOR(4));
	DBMS_OUTPUT.PUT_LINE('index-by table prior b: '||v_idxtable.PRIOR('b'));
END;
/

--result
array prior-9: 
array prior1: 
array prior4: 3
nested table prior-9: 
nested table prior1: 
nested table prior4: 3
index-by table prior b: a

# EXISTS

syntax
varray_type nested_table_type indexby_table_type . exists ( expr )

EXISTS为一个函数,用于判断输入索引位置是否有成员存在。输入的索引存在,函数返回TRUE;输入的索引不存在,函数返回FALSE;输入的索引为NULL时函数返回NULL。

expr为一个YashanDB认可的通用表达式,其结果的数据类型必须符合集合的索引数据类型,否则会进行隐式类型转换。

示例

DECLARE
	TYPE char_array IS ARRAY(5) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idxby_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_char char_array := char_array('1','2','');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxtable idxby_table := idxby_table('b'=>1,'a'=>2,'e'=>3);
BEGIN
	DBMS_OUTPUT.PUT_LINE('array exists-9: '||v_char.EXISTS(-9));
	DBMS_OUTPUT.PUT_LINE('array exists1: '||v_char.EXISTS(1));
	DBMS_OUTPUT.PUT_LINE('array exists4: '||v_char.EXISTS(4));
	DBMS_OUTPUT.PUT_LINE('nested table exists-9: '||v_t_char.EXISTS(-9));
	DBMS_OUTPUT.PUT_LINE('nested table exists1: '||v_t_char.EXISTS(1));
	DBMS_OUTPUT.PUT_LINE('nested table exists4: '||v_t_char.EXISTS(4));
	DBMS_OUTPUT.PUT_LINE('index-by table exists a: '||v_idxtable.EXISTS('a'));
END;
/

--result
array exists-9: false
array exists1: true
array exists4: false
nested table exists-9: false
nested table exists1: true
nested table exists4: false
index-by table exists a: true

# EXTEND

syntax
varray_type nested_table_type . extend ( expr1 , expr2 )

EXTEND为一个存储过程,用于拓展集合的当前成员数量,扩展值为expr2所在成员值(成员必须存在),拓展个数为expr1个(对于数组,拓展后成员数量不能超过数组上限)。

关联数组无法使用EXTEND。

expr1/expr2为一个YashanDB认可的通用表达式,其结果必须为一个非负数字(为NULL时表示extend(0))。expr2省略时,表示拓展空值,expr1省略时,表示拓展1个。

示例

DECLARE
	TYPE char_array IS ARRAY(10) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	v_char char_array := char_array('1','2','3');
	v_t_char char_table := char_table(v_char, v_char, v_char);
BEGIN
	v_char.EXTEND();
	v_char.EXTEND(1);
	v_char.EXTEND(1,1);
	v_t_char.EXTEND();
	v_t_char.EXTEND(1);
	v_t_char.EXTEND(1,1);
	DBMS_OUTPUT.PUT_LINE('array count: '||v_char.count());
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_t_char.count());
END;
/

--result
array count: 6
nested table count: 6

# TRIM

syntax
varray_type nested_table_type . trim ( expr )

TRIM为一个存储过程,用于删除集合的末尾expr个成员(包括已被DELETE指定索引或索引范围删除的成员,删除数量不能超过集合当前所有成员数量)。

关联数组无法使用TRIM。

expr为一个YashanDB认可的通用表达式,其结果必须为一个非负数字(为NULL时表示trim(0))。expr省略时,表示删除1个成员。

示例

DECLARE
	TYPE char_array IS ARRAY(10) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	v_char char_array := char_array('1','2','3');
	v_t_char char_table := char_table(v_char, v_char, v_char);
BEGIN
	v_char.trim('');
	v_char.trim;
	v_char.trim(2);
	v_t_char.trim('');
	v_t_char.trim;
	v_t_char.trim(2);
	DBMS_OUTPUT.PUT_LINE('array count: '||v_char.count());
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_t_char.count());
END;
/

--result
array count: 0
nested table count: 0

# DELETE

delete_clear
varray_type nested_table_type indexby_table_type . delete ()
delete_index
nested_table_type indexby_table_type . delete ( expr1 , expr2 )

DELETE为一个存储过程,用于清空集合中的所有成员或删除集合中的指定成员。当给定0个参数时,清空集合中的所有成员。对于嵌套表和关联数组,可以给定1个参数expr1,删除索引为expr1的成员;或给定2个参数expr1和expr2,删除索引在[expr1,expr2]范围内的成员。expr1和expr2可以为NULL或者是不存在的索引,给定的索引范围可以是无效的索引范围。指定索引或索引范围内的成员被删除后,可以重新赋值。

expr1/expr2为一个YashanDB认可的通用表达式,其结果的数据类型必须符合集合的索引数据类型,否则会进行隐式类型转换。

示例

DECLARE
	TYPE char_array IS ARRAY(10) OF CHAR;
	TYPE char_table IS TABLE OF char_array;
	TYPE idxby_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_char char_array := char_array('1','2','3');
	v_t_char char_table := char_table(v_char, v_char, v_char);
	v_idxtable idxby_table := idxby_table('b'=>1,'a'=>2,'e'=>3);
BEGIN
	v_char.DELETE;
	v_t_char.DELETE;
	v_idxtable.DELETE;
	DBMS_OUTPUT.PUT_LINE('array count: '||v_char.count());
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_t_char.count());
	DBMS_OUTPUT.PUT_LINE('index-by table count: '||v_idxtable.count());
END;
/

--result
array count: 0
nested table count: 0
index-by table count: 0

DECLARE
	TYPE nest_table IS TABLE OF INT;
	TYPE idxby_table IS TABLE OF INT INDEX BY VARCHAR(1);
	v_table nest_table := nest_table(2, 1, 3);
	v_idxtable idxby_table := idxby_table('b'=>1,'a'=>2,'e'=>3);
BEGIN
	v_table.DELETE(2);
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_table.count());
    v_table(2) := 4;
	DBMS_OUTPUT.PUT_LINE('nested table count: '||v_table.count());
    DBMS_OUTPUT.PUT_LINE('nested table 2: '||v_table(2));
	v_idxtable.DELETE('c','g');
	DBMS_OUTPUT.PUT_LINE('index-by table count: '||v_idxtable.count());
END;
/

--result
nested table count: 2
nested table count: 3
nested table 2: 4
index-by table count: 2