DMSQL 程序数据类型与操作符

DMSQL程序支持所有的DM SQL数据类型,包括:精确数值数据类型、近似数值数据类型、字符数据类型、多媒体数据类型、一般日期时间数据类型、时间间隔数据类型。

此外,为了进一步提高DMSQL程序的程序设计属性,DMSQL程序还扩展支持了%TYPE、%ROWTYPE、记录类型、数组类型、集合类型和类类型,用户还可以定义自己的子类型。

2.1 常规数据类型

2.1.1 数值数据类型

  1. NUMERIC类型

语法:

NUMERIC[( 精度 [, 标度])]

功能:

NUMERIC数据类型用于存储零、正负定点数。其中:精度是一个无符号整数,定义了总的数字数,精度范围是1至38,标度定义了小数点右边的数字位数,定义时如省略精度,则默认是16。如省略标度,则默认是 0。一个数的标度不应大于其精度。例如:NUMERIC(4,1)定义了小数点前面 3位和小数点后面 1位,共4位的数字,范围在-999.9到999.9。所有NUMERIC数据类型,如果其值超过精度,达梦数据库返回一个出错信息,如果超过标度,则多余的位截断。

如果不指定精度和标度,缺省精度为38。

  1. NUMBER类型

语法:

NUMBER[(精度 [, 标度])]

功能:

与NUMERIC类型相同。

  1. DECIMAL/DEC类型

语法:

DECIMAL[(精度 [, 标度])]

DEC[(精度 [, 标度])]

功能:

与NUMERIC相似。

  1. BIT类型

语法:

BIT

功能:

BIT类型用于存储整数数据1、0或NULL,可以用来支持ODBC和JDBC的布尔数据类型。DM的BIT类型与SQL SERVER2000的BIT数据类型相似。

  1. INTEGER/INT类型

语法:

INTEGER

INT

功能:

用于存储有符号整数,精度为10,标度为0。取值范围为:-2147483648(-2^31)~+2147483647(2^31-1)。

  1. PLS_INTEGER类型

语法:

PLS_INTEGER

功能:

与INTEGER相同。

  1. BIGINT类型

语法:

BIGINT

功能:

用于存储有符号整数,精度为19,标度为0。取值范围为:-9223372036854775808(-2^63)~9223372036854775807(2^63-1)。

  1. TINYINT类型

语法:

TINYINT

功能:

用于存储有符号整数,精度为3,标度为0。取值范围为:-128~+127。

  1. BYTE类型

语法:

BYTE

功能:

与TINYINT相似,精度为3,标度为0。

  1. SMALLINT类型

语法:

SMALLINT

功能:

用于存储有符号整数,精度为5,标度为0。

  1. BINARY类型

语法:

BINARY[(长度 )]

功能:

BINARY数据类型指定定长二进制数据。缺省长度为1个字节,最大长度由数据库页面大小决定,具体可参考《DM8_SQL语言使用手册》1.4.1节。BINARY常量以0x开始,后跟数据的十六进制表示,例如0x2A3B4058。

  1. VARBINARY类型

语法:

VARBINARY[(长度 )]

功能:

VARBINARY数据类型指定变长二进制数据,用法类似BINARY数据类型,可以指定一个正整数作为数据长度。缺省长度为8188个字节,最大长度由数据库页面大小决定,具体可参考《DM8_SQL语言使用手册》1.4.1节。

  1. REAL类型

语法:

REAL

功能:

REAL是带二进制的浮点数,但它不能由用户指定使用的精度,系统指定其二进制精度为24,十进制精度为7。取值范围-3.4E+38 ~ 3.4E + 38。

  1. FLOAT类型

语法:

FLOAT[(精度)]

功能:

FLOAT是带二进制精度的浮点数,精度最大不超过53,如省略精度,则二进制精度为53,十进制精度为15。取值范围为-1.7E+308 ~ 1.7E + 308。

  1. DOUBLE类型

语法:

DOUBLE[(精度)]

功能:

同FLOAT相似,精度最大不超过53。

  1. DOUBLE PRECISION类型

语法:

DOUBLE PRECISION

功能:

该类型指明双精度浮点数,其二进制精度为53,十进制精度为15。取值范围-1.7E + 308 ~1.7E + 308。

2.1.2 字符数据类型

  1. CHAR/CHARACTER类型

语法:

CHAR[(长度)]

CHARACTER[(长度)]

功能:

定长字符串,最大长度由数据库页面大小决定,具体可参考《DM8_SQL语言使用手册》1.4.1节。长度不足时,自动填充空格。

  1. VARCHAR类型

语法:

VARCHAR[(长度)]

功能:

可变长字符串,最大长度由数据库页面大小决定,具体可参考《DM8_SQL语言使用手册》1.4.1节。

2.1.3 多媒体数据类型

  1. TEXT/LONGVARCHAR类型

语法:

TEXT

LONGVARCHAR

功能:

变长字符串类型,其字符串的长度最大为2G-1,可用于存储长的文本串。

  1. IMAGE/LONGVARBINARY类型

语法:

IMAGE

LONGVARBINARY

功能:

可用于存储多媒体信息中的图像类型。图像由不定长的象素点阵组成,长度最大为2G-1字节。该类型除了存储图像数据之外,还可用于存储任何其它二进制数据。

  1. BLOB类型

语法:

BLOB

功能:

BLOB类型用于指明变长的二进制大对象,长度最大为2G-1字节。

  1. CLOB类型

语法:

CLOB

功能:

CLOB类型用于指明变长的字符串,长度最大为2G-1字节。

  1. BFILE类型

语法:

BFILE

功能:

BFILE用于指明存储在操作系统中的二进制文件,文件存储在操作系统而非数据库中,仅能进行只读访问。

2.1.4 日期时间数据类型

DMSQL程序支持的日期时间数据类型分为一般日期时间数据类型、时区数据类型和时间间隔数据类型三类。

2.1.4.1 一般日期时间数据类型

  1. DATE类型

语法:

DATE

功能:

DATE类型包括年、月、日信息,定义了'-4712-01-01'和'9999-12-31'之间任何一个有效的格里高利日期。

  1. TIME类型

语法:

TIME[(小数秒精度)]

功能:

TIME类型包括时、分、秒信息,定义了一个在'00:00:00.000000'和'23:59:59.999999'之间的有效时间。TIME类型的小数秒精度规定了秒字段中小数点后面的位数,取值范围为0~6,如果未定义,缺省精度为0。

  1. TIMESTAMP/DATETIME类型

语法:

TIMESTAMP[(小数秒精度)]

DATETIME[(小数秒精度)]

功能:

TIMESTAMP/DATETIME类型包括年、月、日、时、分、秒信息,定义了一个在'-4712-01-0100:00:00.000000'和'9999-12-31 23:59:59.999999'之间的有效格里高利日期时间。小数秒精度规定了秒字段中小数点后面的位数,取值范围为0~6,如果未定义,缺省精度为6。

2.1.4.2 时区数据类型

  1. TIME WITH TIME ZONE类型

语法:

TIME[(小数秒精度)]WITH TIME ZONE

功能:

描述一个带时区的TIME值,其定义是在TIME类型的后面加上时区信息。时区部分的实质是INTERVAL HOUR TO MINUTE类型,取值范围:-12:59与+14:00之间。例如:TIME '09:10:21 +8:00'。

  1. TIMESTAMP WITH TIME ZONE类型

语法:

TIMESTAMP[(小数秒精度)]WITH TIME ZONE

功能:

描述一个带时区的TIMESTAMP值,其定义是在TIMESTAMP类型的后面加上时区信息。时区部分的实质是INTERVAL HOUR TO MINUTE类型,取值范围:-12:59与+14:00之间。例如:’2009-10-11 19:03:05.0000 -02:10’。

  1. TIMESTAMP WITH LOCAL TIME ZONE类型

语法:

TIMESTAMP[(小数秒精度)]WITH LOCAL TIME ZONE

功能:

描述一个本地时区的TIMESTAMP值,能够将标准时区类型TIMESTAMP WITH TIME ZONE类型转化为本地时区类型,如果插入的值没有指定时区,则默认为本地时区。

2.1.4.3 时间间隔数据类型

DM支持两类十三种时间间隔类型:两类是年-月间隔类和日-时间隔类,它们通过时间间隔限定符区分,前者结合了日期字段年和月,后者结合了时间字段日、时、分、秒。由时间间隔数据类型所描述的值总是有符号的。

对时间间隔类型的介绍见表2.1,需要查看更为详细的信息可参看《DM8_SQL语言使用手册》1.4.3节。

表2.1 DMSQL程序支持的时间间隔数据类型

类型名 类型描述
INTERVAL YEAR(P) 年间隔,即两个日期之间的年数字,P为时间间隔的首项字段精度(后面简称为:首精度)
INTERVAL MONTH(P) 月间隔,即两个日期之间的月数字,P为时间间隔的首精度
INTERVAL DAY(P) 日间隔,即为两个日期/时间之间的日数字,P为时间间隔的首精度
INTERVA L HOUR(P) 时间隔,即为两个日期/时间之间的时数字,P为时间间隔的首精度
INTERVAL MINUTE(P) 分间隔,即为两个日期/时间之间的分数字,P为时间间隔的首精度
INTERVAL SECOND(P,Q) 秒间隔,即为两个日期/时间之间的秒数字,P为时间间隔的首精度,Q为时间间隔秒精度
INTERVAL YEAR(P) TO MONTH 年月间隔,即两个日期之间的年月数字,P为时间间隔的首精度
INTERVAL DAY(P) TO HOUR 日时间隔,即为两个日期/时间之间的日时数字,P为时间间隔的首精度
INTERVAL DAY(P) TO MINUTE 日时分间隔,即为两个日期/时间之间的日时分数字,P为时间间隔的首精度
INTERVAL DAY(P)TO SECOND(Q) 日时分秒间隔,即为两个日期/时间之间的日时分秒数字,P为时间间隔的首精度,Q为时间间隔秒精度
INTERVALL HOUR(P) TO MINUTE 时分间隔,即为两个日期/时间之间的时分数字,P为时间间隔的首精度
INTERVAL HOUR(P) TO SECOND(Q) 时分秒间隔,即为两个日期/时间之间的时分秒数字,P为时间间隔的首精度,Q为时间间隔秒精度
INTERVAL MINUTE(P) TO SECOND(Q) 分秒间隔,即为两个日期/时间之间的分秒间隔,P为时间间隔的首精度,Q为时间间隔秒精度

2.1.5 BOOL/BOOLEAN数据类型

语法:

BOOL

BOOLEAN

功能:

布尔数据类型:TRUE和FALSE。DMSQL程序的布尔类型和INT类型可以相互转化。如果变量或方法返回的类型是布尔类型,则返回值为0或1。TRUE和非0值的返回值为1,FALSE和0值返回为0。

2.2 %TYPE和%ROWTYPE

在许多时候,DMSQL程序变量被用来处理存储在数据库表中的数据。这种情况下,变量应该拥有与表列相同的类型。例如表T(ID
INT, NAME VARCHAR(30))中字段NAME类型为VARCHAR(30)。对应地在DMSQL程序中,我们可以声明一个变量:

DECLARE

	V_NAME VARCHAR(30);

但是如果T中的NAME字段定义发生了变化,比如变为VARCHAR(100)。那么存储过程中的变量V_NAME也要相应修改为:

DECLARE

	V_NAME VARCHAR(100);

如果用户应用中有很多的变量以及DMSQL程序代码,这种处理可能是十分耗时和容易出错的。

为了解决上述问题,DMSQL程序提供了%TYPE类型。%TYPE可以将变量同表列的类型进行绑定。例如:

DECLARE

	V_NAME T.NAME%TYPE;

通过使用%TYPE,V_NAME将拥有T表的NAME列所拥有的类型。如果表T的NAME列类型定义发生变化,V_NAME的类型也随之自动发生变化,而不需要用户手动修改。

例如,使用%TYPE把变量v1的类型和表PERSON.ADDRESS的ADDRESS1列类型进行绑定。

DECLARE

	v_type PERSON.ADDRESS.ADDRESS1%TYPE;

BEGIN

	SELECT ADDRESS1 INTO v_type FROM PERSON.ADDRESS WHERE ADDRESSID=1;

	PRINT v_type;

END;

/

与%TYPE类似,%ROWTYPE将返回一个基于表定义的运算类型,它将一个记录声明为具有相同类型的数据库行。例如:

DECLARE

	V_TREC T % ROWTYPE;

将定义一个记录,该记录中的字段与表T中的行相对应。V_TREC变量会拥有这样的结构:(ID INT, NAME VARCHAR(30))。如果表定义改变了,那么%ROWTYPE定义的变量也会随之改变。

例如,使用%ROWTYPE将变量v_row与表PERSON.ADDRESS的行相对应。

DECLARE

	v_row PERSON.ADDRESS%ROWTYPE;

	cur CURSOR;

BEGIN

	OPEN cur FOR SELECT * FROM PERSON.ADDRESS WHERE ADDRESSID=3;

	FETCH cur INTO v_row;

	PRINT v_row.ADDRESSID;

	PRINT v_row.ADDRESS1;

	CLOSE cur;

END;
建议

在DMSQL程序设计中使用%TYPE和%ROWTYPE是一种非常好的编程风格,它使得DMSQL程序更加灵活,更适应于对数据库的处理。

2.3 记录类型

记录类型是由单行多列的标量类型构成复合类型,类似于C语言中的结构。记录类型提供了处理分立但又作为一个整体单元的相关变量的一种机制。例如:DECLARE V_ID INT; V_NAME VARCHAR(30); 这两个变量在逻辑上是相互关联的,因为它们分别对应表T(ID INT, NAME VARCHAR(30))中的两个字段。如果为这样的变量声明一个记录类型,那么它们之间的关系就十分明显了。

定义记录类型的语法如下:

TYPE <记录类型名> IS RECORD

(<字段名><数据类型> [<default子句>]{,<字段名><数据类型> [<default子句>]});

<default子句> ::= <default子句1> | <default子句2>

<default子句1> ::= DEFAULT <缺省值>

<default子句2> ::= := <缺省值>

通过将需要操作的表结构定义成一个记录,可以方便地对表中的行数据进行操作。在DMSQL程序中使用记录,需要先定义一个RECORD类型,再用该类型声明变量,也可以使用上一小节介绍的%ROWTYPE来创建与表结构匹配的记录。

可以单独对记录中的字段赋值,使用点标记引用一个记录中的字段(记录名.字段名)。

例如,下面的例子定义了一个记录类型sale_person,声明一个该记录类型的变量v_rec,使用点标记为v_rec的两个字段赋值,之后使用v_rec更新表的一行数据。

DECLARE

	TYPE sale_person IS RECORD(

		ID SALES.SALESPERSON.SALESPERSONID%TYPE,

		SALESTHISYEAR SALES.SALESPERSON.SALESTHISYEAR%TYPE);

	v_rec sale_person;

BEGIN

	v_rec.ID := 1;

	v_rec.SALESTHISYEAR:= 5500;

	UPDATE SALES.SALESPERSON SET SALESTHISYEAR=v_rec.SALESTHISYEAR WHERE
SALESPERSONID =v_rec.ID;

END;

/

也可以将一个记录直接赋值给另外一个记录,此时两个记录中的字段类型定义必须完全一致。如下面的例子将表中的一行数据读取到一个记录中。然后,将记录v_rec1赋值给v_rec2。

DECLARE

	TYPE t_rec IS RECORD( ID INT, NAME VARCHAR(50));

	TYPE t_rec_NEW IS RECORD( ID INT, NAME VARCHAR(50));

	v_rec1 T_REC;

	v_rec2 T_REC_NEW;

BEGIN

	SELECT PRODUCTID,NAME INTO v_rec1 FROM PRODUCTION.PRODUCT WHERE AUTHOR LIKE
'鲁迅';

	v_rec2 := v_rec1;

	PRINT v_rec2.ID;

	PRINT v_rec2.NAME;

END;

/

定义记录类型时,字段的数据类型除了可以是常规数据类型,还可以是常规数据类型后跟着“[n]”或“[n1,n2...]”表示一维或多维数组,如:

DECLARE

	TYPE T_REC IS RECORD( ID INT[3], NAME VARCHAR(30)[3]);

DMSQL程序还支持定义包含数组、集合和其他RECORD的RECORD。例如下面是一个在RECORD定义中包含其他RECORD的例子,关于数组和集合的介绍请看后续小节。

DECLARE

	TYPE TimeType IS RECORD (hours INT, minutes INT ); --定义记录TimeType

	TYPE MeetingType IS RECORD (

	day DATE,

	time_of TimeType -- 嵌套记录TimeType

);

BEGIN

	NULL;

END;

/

2.4 数组类型

DMSQL程序支持数组数据类型,包括静态数组类型和动态数组类型。

注意

DM数组下标的起始值为1。

2.4.1 静态数组类型

静态数组是在声明时已经确定了数组大小的数组,其长度是预先定义好的,在整个程序中,一旦给定大小后就无法改变。

定义静态数组类型的语法图例如下:

定义静态数组类型的语法图例 表示正文的附加信息,是对正文的强调和补充。

定义了静态数组类型后需要用这个类型申明一个数组变量然后进行操作。

理论上DM支持静态数组的每一个维度的最大长度为65534,但是静态数组最大长度同时受系统内部堆栈空间大小的限制,如果超出堆栈的空间限制,系统会报错。

下面是一个使用静态数组的例子:

DECLARE

	TYPE Arr IS ARRAY VARCHAR[3]; --TYPE定义一维数组类型

	a Arr; --声明一维数组

	TYPE Arr1 IS ARRAY VARCHAR[2,4]; --TYPE定义二维数组类型

	b Arr1; --声明二维数组

BEGIN

	FOR I IN 1..3 LOOP

		a[I] := I * 10;

		PRINT a[I];

	END LOOP;

	PRINT '--------';

	FOR I IN 1..2 LOOP

		FOR J IN 1..4 LOOP

			b[I][J] = 4*(I-1)+J;

			PRINT b[I][J];

		END LOOP;

	END LOOP;

END;

/

2.4.2 动态数组类型

与静态数组不同,动态数组可以随程序需要而重新指定大小,其内存空间是从堆(HEAP)上分配(即动态分配)的,通过执行代码而为其分配存储空间,并由DM自动释放内存。

动态数组与静态数组的定义方法类似,区别只在于动态数组没有指定下标,需要动态分配空间。定义动态数组类型的语法图例如下:

定义动态数组类型的语法图例

定义了动态数组类型后需要用这个类型申明一个数组变量,之后在DMSQL程序的执行部分需要为这个数组变量动态分配空间。动态分配空间语句如下所示:

数组变量名 := NEW 数据类型[常量表达式,…];

或者可以使用如下语句对多维数组的某一维度进行空间分配:

数组变量名 := NEW 数据类型[常量表达式][];

下面给出了一个使用动态数组的例子:

DECLARE

	TYPE Arr IS ARRAY VARCHAR[];

	a Arr;

BEGIN

	a := NEW VARCHAR[4];--动态分配空间

	FOR I IN 1..4 LOOP

		a[I] := I * 4;

		PRINT a[I];

	END LOOP;

END;

/

对于多维动态数组,可以单独为每个维度动态分配空间,如下面的例子所示:

DECLARE

	TYPE Arr1 IS ARRAY VARCHAR[,];

	b Arr1;

BEGIN

	b := NEW VARCHAR[2][];--动态分配第一维空间

	FOR I IN 1..2 LOOP

		b[I] := NEW VARCHAR[4]; --动态分配第二维空间

		FOR J IN 1..4 LOOP

			b[I][J] = I*10+J;

			PRINT b[I][J];

		END LOOP;

	END LOOP;

END;

/

也可以一次性为多维动态数组分配空间,则上面的例子可以写为:

DECLARE

	TYPE Arr1 IS ARRAY VARCHAR[,];

	b ARR1;

BEGIN

	b := NEW VARCHAR[2,4];

	FOR I IN 1..2 LOOP

		FOR J IN 1..4 LOOP

			b[I][J]= I*10+J;

			PRINT b[I][J];

		END LOOP;

	END LOOP;

END;

/

理论上DM支持动态数组的每一个维度的最大长度为2147483646,但是数组最大长度同时受系统内部堆空间大小的限制,如果超出堆的空间限制,系统会报错。

2.4.3 复杂类型数组

除了普通数据类型的数组,DM还支持自定义类型、记录类型和集合类型的数组。

在下面的例子中,定义了一个自定义类型(OBJECT类型)的静态数组,存放图书的序号和名称。

CREATE OR REPLACE TYPE COMPLEX AS OBJECT(

	RPART INT,

	IPART VARCHAR(100)

);

/

DECLARE

	TYPE ARR_COMPLEX IS ARRAY SYSDBA.COMPLEX[3];

	arr ARR_COMPLEX;

BEGIN

	FOR I IN 1..3 LOOP

		SELECT SYSDBA.COMPLEX(PRODUCTID, NAME) INTO arr[I] FROM PRODUCTION.PRODUCT WHERE
PRODUCTID=I;

		PRINT arr[I].RPART || arr[I].IPART;

	END LOOP;

END;

/

也可以将上例中的对象类型改为记录类型,则DMSQL程序可写为:

DECLARE

	TYPE REC IS RECORD(ID INT, NAME VARCHAR(128));

	TYPE REC_ARR IS ARRAY REC[3];

	arr REC_ARR;

BEGIN

	FOR I IN 1..3 LOOP

		SELECT PRODUCTID, NAME INTO arr[I] FROM PRODUCTION.PRODUCT WHERE PRODUCTID=I;

		PRINT arr[I].ID || arr[I].NAME;

	END LOOP;

END;

/

下面的例子定义了一个集合类型(以VARRAY为例)的数组,将员工的姓名、性别和职位信息存放到数组变量中。

DECLARE

	TYPE VARY IS VARRAY(3) OF varchar(100);

	TYPE ARR_VARY IS ARRAY VARY[8];

	arr ARR_VARY;

	v1,v2,v3 varchar(50);

BEGIN

	FOR I IN 1..8 LOOP

		SELECT NAME,PERSON.SEX,TITLE INTO v1,v2,v3 FROM PERSON.PERSON,RESOURCES.EMPLOYEE
WHERE PERSON.PERSONID=EMPLOYEE.PERSONID AND PERSON.PERSONID=I;

		arr[I] := VARY(v1,v2,v3);

		PRINT '*****工号'||I||'*****';

		FOR J IN 1..3 LOOP

			PRINT arr[I][J];

		END LOOP;

	END LOOP;

END;

/

2.5 集合类型

DMSQL程序支持三种集合类型:VARRAY类型、索引表类型和嵌套表类型。

2.5.1 VARRAY

VARRAY是一种具有可伸缩性的数组,数组中的每个元素具有相同的数据类型。VARRAY在定义时由用户指定一个最大容量,其元素索引是从1开始的有序数字。

定义VARRAY的语法格式为:

TYPE<数组名> IS VARRAY(<常量表达式>) OF <数据类型>;

\<常量表达式\>表示数组的最大容量。

\<数据类型\>是VARRAY中元素的数据类型,可以是常规数据类型,也可以是其他自定义类型或对象、记录、其他VARRAY类型等,使得构造复杂的结构成为可能。

在定义了一个VARRAY数组类型后,再声明一个该数组类型的变量,就可以对这个数组变量进行操作了。如下面的代码片段所示:

TYPE my_array_type IS VARRAY(10) OF INTEGER;

	v MY_ARRAY_TYPE;

使用v.COUNT()方法可以得到数组v当前的实际大小,v.LIMIT()则可获得数组v的最大容量。需要注意的是,VARRAY的元素索引总是连续的。

下面给出一个VARRAY的简单使用示例,查询人员姓名并将其存入一个VARRAY变量中。VARRAY最初的实际大小为0,使用EXCTEND()方法可扩展VARRAY元素个数,具体在2.5.4节中介绍。

DECLARE

	TYPE MY_ARRAY_TYPE IS VARRAY(10) OF VARCHAR(100);

	v MY_ARRAY_TYPE;

BEGIN

	v:=MY_ARRAY_TYPE();

	PRINT 'v.COUNT()=' || v.COUNT();

	FOR I IN 1..8 LOOP

		v.EXTEND();

		SELECT NAME INTO v(I) FROM PERSON.PERSON WHERE PERSON.PERSONID=I;

END LOOP;

	PRINT 'v.COUNT()=' || v.COUNT();

	FOR I IN 1..v.COUNT() LOOP

		PRINT 'v(' || i || ')=' ||v(i);

	END LOOP;

END;

/

2.5.2 索引表

索引表提供了一种快速、方便地管理一组相关数据的方法。索引表是一组数据的集合,它将数据按照一定规则组织起来,形成一个可操作的整体,是对大量数据进行有效组织和管理的手段之一,通过函数可以对大量性质相同的数据进行存储、排序、插入及删除等操作,从而可以有效地提高程序开发效率及改善程序的编写方式。

索引表不需要用户指定大小,其大小根据用户的操作自动增长。

定义索引表的语法格式为:

TYPE <索引表名> IS TABLE OF<数据类型> INDEX BY <索引数据类型>;

“数据类型”指索引表存放的数据的类型,这个数据类型可以是常规数据类型,也可以是其他自定义类型或是对象、记录、静态数组,但不能是动态数组;“索引数据类型”则是索引表中元素索引的数据类型,DM目前仅支持INTEGER/INT和VARCHAR两种类型,分别代表整数索引和字符串索引。对于VARCHAR类型,长度不能超过1024。

用户可使用“索引-数据”对向索引表插入数据,之后可通过“索引”修改和查询这个数据,而不需要知道数据在索引表中实际的位置。

下面给出了一个非常简单的索引表的使用示例。

DECLARE

	TYPE Arr IS TABLE OF VARCHAR(100) INDEX BY INT;

	x Arr;

BEGIN

	x(1) := 'TEST1';

	x(2) := 'TEST2';

	x(3) := x(1) || x(2);

	PRINT x(3);

END;

/

索引表还可以用来管理记录,下面的例子索引表中存放的数据类型为RECORD,展示了如何存入和遍历输出索引表的记录类型数据。

DECLARE

	TYPE Rd IS RECORD(ID INT, NAME VARCHAR(128));

	TYPE Arr IS TABLE OF Rd INDEX BY INT;

	x Arr;

	i INT;

	CURSOR C1;

BEGIN

	i := 1;

	OPEN C1 FOR SELECT PERSONID, NAME FROM PERSON.PERSON;

--遍历结果集,把每行的值都存放入索引表中

	LOOP

		IF C1%NOTFOUND THEN

			EXIT;

		END IF;

		FETCH C1 INTO x(i).ID, x(i).NAME;

		i := i + 1;

	END LOOP;

--遍历输出索引表中的记录

	i = x."FIRST"();

	LOOP

		IF i IS NULL THEN

			EXIT;

		END IF;

		PRINT 'ID:' || CAST(x(i).ID AS VARCHAR(10)) || ', NAME:' || x(i).NAME;

		i = x."NEXT"(i);

	END LOOP;

END;

/

下面的例子定义了一个二维索引表x,展示了如何存入和遍历输出二维索引表的数据。

DECLARE

	TYPE Arr IS TABLE OF VARCHAR(100) INDEX BY BINARY_INTEGER;

	TYPE Arr2 IS TABLE OF Arr INDEX BY VARCHAR(100);

	x Arr2;

	ind_i INT;

	ind_j VARCHAR(10);

BEGIN

--存入数据

	FOR I IN 1 .. 6 LOOP

		FOR J IN 1 .. 3 LOOP

			x(I)(J) := CAST(I AS VARCHAR(100)) || '+'||CAST(J AS VARCHAR(10));

		END LOOP;

	END LOOP;

--遍历多维数组

	ind_i := x."FIRST"();

	LOOP

		IF ind_i IS NULL THEN

			EXIT;

		END IF;

		ind_j := x(ind_i)."FIRST"();

		LOOP

			IF ind_j IS NULL THEN

				EXIT;

			END IF;

			PRINT x(ind_i)(ind_j);

			ind_j := x(ind_i)."NEXT"(ind_j);

		END LOOP;

		ind_i := x."NEXT"(ind_i);

	END LOOP;

END;

/

2.5.3 嵌套表

嵌套表类似于一维数组,但与数组不同的是,嵌套表不需要指定元素的个数,其大小可自动扩展。嵌套表元素的下标从1开始。

定义嵌套表的语法格式为:

TYPE <嵌套表名> IS TABLE OF <元素数据类型>;

元素数据类型用来指明嵌套表元素的数据类型,当元素数据类型为一个定义了某个表记录的对象类型时,嵌套表就是某些行的集合,实现了表的嵌套功能。

下面的例子定义了一个嵌套表,其结构与SALES.SALESPERSON表相同,用来存放今年销售额大于1000万的销售代表的信息。

DECLARE

	TYPE Info_t IS TABLE OF SALES.SALESPERSON%ROWTYPE;

	info Info_t;

BEGIN

	SELECT SALESPERSONID,EMPLOYEEID,SALESTHISYEAR,SALESLASTYEAR BULK COLLECT INTO
info FROM SALES.SALESPERSON WHERE SALESTHISYEAR>1000;

END;

/

2.5.4 集合类型支持的方法

DM为VARRAY、索引表和嵌套表提供了一些方法,用户可以使用这些方法访问和修改集合与集合元素。

  1. COUNT

语法:

<集合变量名>.COUNT

功能:

返回集合中元素的个数。

  1. LIMIT

语法:

<VARRAY变量名>.LIMIT

功能:

返回VARRAY集合的最大的元素个数,对索引表和嵌套表不适用。

  1. FIRST

语法:

<集合变量名>.FIRST

功能:

返回集合中的第一个元素的下标号,对于VARRAY集合始终返回1。

  1. LAST

语法:

<集合变量名>.LAST

功能:

返回集合中最后一个元素的下标号,对于VARRAY返回值始终等于COUNT。

  1. NEXT

语法:

<集合变量名>.NEXT(<下标>)

参数:

指定的元素下标。

功能:

返回在指定元素i之后紧挨着它的元素的下标号,如果指定元素是最后一个元素,则返回NULL。

  1. PRIOR

语法:

<集合变量名>.PRIOR(<下标>)

参数:

指定的元素下标。

功能:

返回在指定元素i之前紧挨着它的元素的下标号,如果指定元素是第一个元素,则返回NULL。

  1. EXISTS

语法:

<集合变量名>.EXISTS(<下标>)

参数:

指定的元素下标。

功能:

如果指定下标对应的元素已经初始化,则返回TRUE,否则返回FALSE。

  1. DELETE

语法:

<集合变量名>.DELETE([<下标>])

参数:

待删除元素的下标。

功能:

下标参数省略时删除集合中所有元素,否则删除指定下标对应的元素,如果指定下标为NULL,则集合保持不变。

  1. DELETE

语法:

<集合变量名>.DELETE(<下标1>, <下标2>)

参数:

下标1:要删除的第一个元素的下标;

下标2:要删除的最后一个元素的下标。

功能:

删除集合中下标从下标1到下标2的所有元素。

  1. TRIM

语法:

<集合变量名>.TRIM([<n>])

参数:

删除元素的个数。

功能:

n参数省略时从集合末尾删除一个元素,否则从集合末尾开始删除n个元素。本方法不适用于索引表。

  1. EXTEND

语法:

<集合变量名>.EXTEND([<n>])

参数:

扩展元素的个数。

功能:

n参数省略时在集合末尾扩展一个空元素,否则在集合末尾扩展n个空元素。本方法不适用于索引表。

  1. EXTEND

语法:

<集合变量名>.EXTEND(<n>,<下标>])

参数:

n:扩展元素的个数;

下标:待复制元素的下标。

功能:

在集合末尾扩展n个与指定下标元素相同的元素。本方法不适用于索引表。

下面的例子简单演示了如何使用集合类型的方法:

DECLARE

	TYPE IntList IS TABLE OF INT;

	v IntList := IntList(1,3,5,7,9); -- 开始赋值5个元素.

BEGIN

	DBMS_OUTPUT.PUT_LINE

		('最初v中共有 ' || v.COUNT || '个元素。');

	v.EXTEND(3);-- 在末尾增加三个元素

	DBMS_OUTPUT.PUT_LINE

		('现在v中共有 ' || v.COUNT || '个元素。');

	v.DELETE(2); --删掉第2个元素

	DBMS_OUTPUT.PUT_LINE

		('现在v中共有 ' || v.COUNT || '个元素。');

	v.TRIM(2); -- 删除掉末尾的两个元素

	DBMS_OUTPUT.PUT_LINE

		('现在v中共有 ' || v.COUNT || '个元素。');

END;

/

2.6 类类型

DM支持类类型,类将结构化的数据及对其进行操作的过程或函数封装在一起。允许用户根据现实世界的对象建模,而不必再将其抽象成关系数据。关于类类型的详细介绍可以参考《DM8_SQL语言使用手册》的相关章节。

DMSQL程序中可以声明一个类类型的变量,初始化该变量后就可以访问类的成员变量,调用类的成员方法了。

2.7 子类型

子类型是其基数据类型的子集。子类型具有与基数据类型相同的操作性质,但是其有效值域是基数据类型的子集。

定义子类型的语法如下:

SUBTYPE <subtype_name> IS <base_type>[(<精度>,[<刻度>])] [NOT NULL];

例如:

DECLARE

	SUBTYPE COUNTER IS NUMBER(5);

	C COUNTER;

BEGIN

	NULL;

END;

在这个例子中定义了一个名称为COUNTER的子类型,其实际数据类型为NUMBER(5)。子类型可用来防止变量超出规定的值域,也可以增强DMSQL程序的可读性。

可以在任何DMSQL程序块、子程序或包中定义自己的子类型。一旦定义了子类型,就可以声明该类型的变量、常量等,如上例中的变量C。

2.8 操作符

与其他程序设计语言相同,DMSQL程序有一系列操作符。操作符分为下面几类:

  • 算术操作符
  • 关系操作符
  • 比较操作符
  • 逻辑操作符

算术操作符如表2.1所示。

表2.1 算术操作符

操作符 对应操作
+
-
*
/

关系操作符主要用于条件判断语句或用于WHERE子句中,关系操作符检查条件和结果为TRUE或FALSE。表2.2、表2.3、表2.4分别列出了DMSQL程序中的关系操作符、比较操作符和逻辑操作符。

表2.2关系操作符

操作符 对应操作
< 小于操作符
<= 小于或等于操作符
> 大于操作符
>= 大于或等于操作符
= 等于操作符
!= 不等于操作符
<> 不等于操作符
:= 赋值操作符

表2.3比较操作符

操作符 对应操作
IS NULL 如果操作数为NULL返回TRUE
LIKE 比较字符串值
BETWEEN 验证值是否在范围之内
IN 验证操作数在设定的一系列值中

表2.4逻辑操作符

操作符 对应操作
AND 两个条件都必须满足
OR 只要满足两个条件中的一个
NOT 取反
微信扫码
分享文档
扫一扫
联系客服