本文介绍了自定义子类型的语法及示例等内容。
语法
PL/SQL允许用户自定义子类型(subtype),即在基本类型的基础上增加一些限制。
自定义子类型定义的语法如下:
SUBTYPE subtype_name IS base_type
[precision [, scale ] | RANGE low_value .. high_value ] [ NOT NULL ];
示例
DECLARE
SUBTYPE subtype_char IS VARCHAR(10);
sub_var subtype_char;
base_var VARCHAR(10);
BEGIN
NULL;
END;
其中,sub_var
和base_var
的类型实际上是一致的,都表示了一个长度受到限制的varchar类型。基本类型可以是任何标量或用户定义的PL/SQL数据类型说明符。例如,CHAR或RECORD。
示例一:
DECLARE TYPE r_type IS RECORD(id INT, name VARCHAR(10)); SUBTYPE subtype_record IS r_type; rec subtype_record; BEGIN rec.id := 1; rec.name := 'a'; RAISE NOTICE 'rec = %', rec; END;
结果显示如下:
NOTICE: rec = (1,a) DO
示例二:
DECLARE SUBTYPE subtype_char IS VARCHAR; SUBTYPE sub_subtype_char IS subtype_char; sub_var sub_subtype_char; BEGIN sub_var := 'a'; RAISE NOTICE 'sub_var = %', sub_var; END;
结果显示如下:
NOTICE: sub_var = a DO
无约束的子类型
无约束的子类型只是其基本类型的另一个名称,因此它和它的基本类型拥有相同的值集。相同基本类型的子类型之间,或者基本类型与子类型之间进行赋值时,不产生数据类型转换。无约束的子类型定义语法如下:
SUBTYPE subtype_name IS base_type;
受约束的子类型
受约束的子类型仅具有其基本类型的值的子集。如果基本类型允许指定大小、精度和小数位数或值范围,则可以为其子类型指定这些限制。受约束的子类型定义语法如下:
SUBTYPE subtype_name IS base_type
{ precision [, scale ] | RANGE low_value .. high_value } [ NOT NULL ]
示例
您可以使用NOT NULL
关键字对使用该子类型的变量施加非空约束,也可以对基本类型为PLS_INTEGER
的子类型使用RANGE
关键字来施加取值范围的约束。
受约束的子类型可以隐式转换为其基本类型,但只有当值不违反子类型的约束时,基本类型才能隐式转换为受约束的子类型。
在一个受约束子类型的变量赋值给另一个受约束子类型的变量时,不仅要满足隐式转换的要求,还需要满足目标子类型的各项约束。
以下展示了一些在赋值时不满足约束条件的示例:
精度约束
DECLARE SUBTYPE subtype_number IS NUMBER(8,2); var1 subtype_number; var2 subtype_number; BEGIN var1 := 100000.00; -- 赋值成功 RAISE NOTICE 'var1 = %' , var1; var2 := 1000000.00; -- 赋值失败 END;
显示结果如下:
NOTICE: var1 = 100000 ERROR: numeric field overflow DETAIL: A field with precision 8, scale 2 must round to an absolute value less than 10^6. CONTEXT: PL/SQL assignment "var2 := 1000000.00"
取值范围约束
DECLARE SUBTYPE subtype_range IS PLS_INTEGER RANGE 0..9; var subtype_range := 4; -- 赋值成功 BEGIN RAISE NOTICE 'var = %', var; var := 10; -- 赋值失败 END;
显示结果如下:
NOTICE: var = 4 ERROR: the assignment of variable "var" is out of range, since it's declared between 0 and 9 CONTEXT: PL/SQL function inline_code_block line 6 at assignment
非空约束
DECLARE SUBTYPE subtype_range IS INT NOT NULL; var subtype_range := 1; BEGIN RAISE NOTICE 'var = %', var; var := NULL; -- 赋值失败 END;
显示结果如下:
NOTICE: var = 1 ERROR: null value cannot be assigned to variable "var" declared NOT NULL CONTEXT: PL/SQL function inline_code_block line 5 at assignment
隐式类型转换
DECLARE SUBTYPE subtype_int IS INT; SUBTYPE subtype_char IS CHAR(3); var1 subtype_int := 100; var2 subtype_char; BEGIN var2 := var1; -- 赋值成功 RAISE NOTICE 'var2 = %', var2; var1 := 1000; var2 := var1; -- 赋值失败 END;
显示结果如下:
NOTICE: var2 = 100 ERROR: value too long for type character(3 char) CONTEXT: PL/SQL function inline_code_block line 10 at assignment
子类型作为局部函数的入参类型和返回值类型
子类型和其他局部类型一样,可以作为局部函数的入参类型和返回值类型。
示例
DECLARE
SUBTYPE sub_type IS VARCHAR(20);
PROCEDURE outer_proc IS
outer_var sub_type; -- 使用外层的局部类型sub_type
FUNCTION inner_func(name sub_type) RETURN sub_type IS
BEGIN
RETURN name || 'inner'; -- 返回了类型为sub_type的返回值
END;
BEGIN
outer_var := inner_func('outer-'); -- 调用局部函数inner_func
RAISE NOTICE '%', outer_var;
END;
BEGIN
outer_proc; -- 首先调用局部过程outer_proc
END;
结果显示如下:
NOTICE: outer-inner
DO
说明
由于OUT类型的入参会把传入变量初始化为NULL,因此如果入参类型为具有非空约束的子类型时,会直接报错:
DECLARE
SUBTYPE sub_type IS PLS_INTEGER NOT NULL;
a sub_type := 1;
PROCEDURE proc_test(id OUT sub_type) IS
BEGIN
NULL;
END;
BEGIN
proc_test(a); -- 报错
END;
显示结果如下:
ERROR: null value cannot be assigned to variable "a" declared NOT NULL
CONTEXT: PL/SQL function inline_code_block line 3 at CALL
该文章对您有帮助吗?