#集合变量
YashanDB包含如下三种集合变量:
- 可变长数组(VARRAY):一个可变长数组包含一组相同类型的成员,成员在数组内有序存放。
- 嵌套表(NESTED TABLE):一个嵌套表包含多行相同类型的成员,类似于物理表记录存储,行成员在嵌套表中无序存放。使用嵌套表可以更方便地实现多维数组的定义和操作。
- 关联数组(INDEX-BY TABLE):一个关联数组包含多个键值对成员,每个键是一个唯一的索引,键值对成员按索引有序存放。
三者对比 | VARRAY | NESTED TABLE | INDEX-BY TABLE |
---|---|---|---|
成员个数限制 | 在定义时必须声明其最大长度,实际长度(即成员个数)在此范围内动态改变 | 实际长度(即成员个数)可在资源允许范围内一直动态扩展 | 实际长度(即成员个数)可在资源允许范围内一直动态扩展 |
成员存放方式 | 成员有序存放 | 行成员无序存放 | 键值对成员按索引有序存放 |
成员数据类型 | 可以为除游标类型外的任何PL数据类型 | 可以为除游标类型外的任何PL数据类型 | * 索引:可以为INTEGER、PLS_INTEGER、BINARY_INTEGER、VARCHAR类型 * 值:可以为除游标类型外的任何PL数据类型 |
定义方式 | * 可在过程体内部定义 * 可作为UDT在过程体外部定义 | * 可在过程体内部定义 * 可作为UDT在过程体外部定义 | 仅支持在过程体内部定义 |
其他 | - | - | 对于关联数组而言,声明即初始化 |
# 集合变量声明
声明集合变量前需进行集合类型的定义,在过程体内部定义集合变量的语法为:
对集合变量的声明语法为:
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_ARRAY、ARRAY_APPEND、ARRAY_REMOVE、ARRAY_REPLACE等。
# 集合变量访问
一个已被赋值的集合变量可以通过如下语法访问:
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
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
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
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
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
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
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
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
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
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为一个存储过程,用于清空集合中的所有成员或删除集合中的指定成员。当给定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