1. 动态数组(VARRAY)
1.1 定义
VARRAY是一个动态数组,大小可伸缩。数组中每个元素具有相同的数据类型。在定义时需指定最大容量,元素索引为1开始的有序数字定义如下:
TYPE <数组名> IS VARRAY(<常量表达式>) OF <数据类型>;
1.2 动态数组使用
1.2.1 存取局部变量
DECLARE
TYPE ARR IS VARRAY(100) OF VARCHAR(100);
VARR ARR;
I INT;
BEGIN
VARR = ARR();
VARR.EXTEND(1);
VARR(1) := '200';
I = VARR.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'VARR(' || I || '): ' || VARR(I);
I := VARR.NEXT(I);
END LOOP;
END;
运行结果
注:动态数组实际默认长度为0。使用时需要使用EXTEND()函数扩容。参数选填。表示扩容多少位元素,不填默认扩展一位。 扩展大小不能超过定义最大大小。
1.2.1 存取单列数据
DECLARE
TYPE VARR IS VARRAY(100) OF VARCHAR(50);
NAMES VARR;
I INT;
BEGIN
NAMES = VARR();
SELECT NAME BULK COLLECT INTO NAMES FROM PERSON.PERSON;
I = NAMES.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'NAMES(' || I || '): ' || NAMES(I);
I := NAMES.NEXT(I);
END LOOP;
END;
运行结果:
可以看到,当使用BULK COLLECT INTO 读取时,会自动扩展,不用显式扩容。
1.2.3 存取表记录
DECLARE
TYPE VARR IS VARRAY(100) OF PERSON.PERSON%ROWTYPE;
NAMES VARR;
I INT;
BEGIN
NAMES = VARR();
SELECT * BULK COLLECT INTO NAMES FROM PERSON.PERSON;
I = NAMES.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'PERSONID: ' || NAMES(I).PERSONID;
PRINT 'SEX: ' || NAMES(I).SEX;
PRINT 'NAME: ' || NAMES(I).NAME;
PRINT 'EMAIL: ' || NAMES(I).EMAIL;
PRINT 'PHONE: ' || NAMES(I).PHONE;
PRINT '-------';
I := NAMES.NEXT(I);
END LOOP;
END;
运行结果:
2. 索引表
2.1 定义
索引表是一组数据的集合,定义如下:
TYPE <索引表名> IS TABLE OF <数据类型> INDEX BY <索引数据类型>;
数据类型:指存放的数据的类型,可以是常规类型,也可以是自定义类型。不能是动态数组。因此可定义多维索引表。(笔者只验证过最高二维)
索引数据类型:索引表中元素索引的数据类型。仅支持INTEGER/INT和VARCHAR类型。VARCHAR类型长度不能超过1024。
2.2 索引表使用
2.2.1 存取局部变量
DECLARE
TYPE ARR IS TABLE OF VARCHAR(100) INDEX BY INT;
VARR ARR;
I INT;
BEGIN
VARR(-1) := '100';
VARR(1) := '200';
VARR(3) := '400';
I = VARR.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'VARR(' || I || '): ' || VARR(I);
I := VARR.NEXT(I);
END LOOP;
END;
运行结果:
2.2.2 存取表单列数据
--遍历单列
DECLARE
TYPE NAMEARR IS TABLE OF VARCHAR(50) INDEX BY INT;
NAMES NAMEARR;
I INT;
BEGIN
SELECT NAME BULK COLLECT INTO NAMES FROM PERSON.PERSON;
I := NAMES.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'NAMES(' || I || ')' || NAMES(I);
I = NAMES.NEXT(I);
END LOOP;
END;
运行结果:
2.2.3 存取表记录
--遍历表记录
DECLARE
TYPE RCD IS RECORD (
PERSONID INT,
SEX CHAR(1),
NAME VARCHAR(50),
EMAIL VARCHAR(50),
PHONE VARCHAR(25)
);
TYPE ARR IS TABLE OF RCD;
RECD ARR;
VSQL VARCHAR(1024);
I INT;
BEGIN
VSQL := 'SELECT * FROM PERSON.PERSON;';
EXECUTE IMMEDIATE VSQL BULK COLLECT INTO RECD;
I := RECD.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'PERSONID: ' || RECD(I).PERSONID;
PRINT 'SEX: ' || RECD(I).SEX;
PRINT 'NAME: ' || RECD(I).NAME;
PRINT 'EMAIL: ' || RECD(I).EMAIL;
PRINT 'PHONE: ' || RECD(I).PHONE;
PRINT '-------';
I = RECD.NEXT(I);
END LOOP;
END;
运行结果
存取表记录除了使用动态数组,索引表,还可使用嵌套表。
3. 嵌套表
3.1 定义
嵌套表类似数组,但不需要指定元素个数。 定义如下:
TYPE<嵌套表名> IS TABLE OF <元素数据类型>;
3.2.1 存取局部变量
DECLARE
TYPE ARR IS TABLE OF VARCHAR(100);
VARR ARR;
I INT;
BEGIN
VARR = ARR();
VARR.EXTEND();
VARR(1) := '200';
I = VARR.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'VARR(' || I || '): ' || VARR(I);
I := VARR.NEXT(I);
END LOOP;
END;
运行结果:
3.2.2 存取表单列
DECLARE
TYPE VARR IS VARRAY(100) OF PERSON.PERSON.NAME%TYPE;
NAMES VARR;
I INT;
BEGIN
NAMES = VARR();
SELECT NAME BULK COLLECT INTO NAMES FROM PERSON.PERSON;
I = NAMES.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'NAMES(' || I || '): ' || NAMES(I);
I := NAMES.NEXT(I);
END LOOP;
END;
运行结果:
3.2.3 存取表记录
DECLARE
TYPE VARR IS TABLE OF PERSON.PERSON%ROWTYPE;
NAMES VARR;
I INT;
BEGIN
NAMES = VARR();
SELECT * BULK COLLECT INTO NAMES FROM PERSON.PERSON;
I = NAMES.FIRST();
LOOP
IF I IS NULL THEN
EXIT;
END IF;
PRINT 'PERSONID: ' || NAMES(I).PERSONID;
PRINT 'SEX: ' || NAMES(I).SEX;
PRINT 'NAME: ' || NAMES(I).NAME;
PRINT 'EMAIL: ' || NAMES(I).EMAIL;
PRINT 'PHONE: ' || NAMES(I).PHONE;
PRINT '-------';
I := NAMES.NEXT(I);
END LOOP;
END;
运行记录:
4. 总结
从上述实验可看出,动态数组(VARRAY)和嵌套表极其相似。区别在于定义时嵌套表不用指定长度。两者对于通过下标的存储数据均需初始化以及使用EXTEND()函数进行扩容,且动态数字大小不能超过定义大小。两者下标均为1开始的连续数字。而索引表索引类型还可以为VARCHAR类型,VARCHAR类型长度不超过1024。下标与数据的对应关系更类似于链表或者键值对。(具体未细究)
更多达梦关技术文档可访问