子類型
本文介紹了自定義子類型的語法及示例等內(nèi)容。
語法
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數(shù)據(jù)類型說明符。例如,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;
結(jié)果顯示如下:
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;
結(jié)果顯示如下:
NOTICE: sub_var = a DO
無約束的子類型
無約束的子類型只是其基本類型的另一個名稱,因此它和它的基本類型擁有相同的值集。相同基本類型的子類型之間,或者基本類型與子類型之間進行賦值時,不產(chǎn)生數(shù)據(jù)類型轉(zhuǎn)換。無約束的子類型定義語法如下:
SUBTYPE subtype_name IS base_type;
受約束的子類型
受約束的子類型僅具有其基本類型的值的子集。如果基本類型允許指定大小、精度和小數(shù)位數(shù)或值范圍,則可以為其子類型指定這些限制。受約束的子類型定義語法如下:
SUBTYPE subtype_name IS base_type
{ precision [, scale ] | RANGE low_value .. high_value } [ NOT NULL ]
示例
您可以使用NOT NULL
關(guān)鍵字對使用該子類型的變量施加非空約束,也可以對基本類型為PLS_INTEGER
的子類型使用RANGE
關(guān)鍵字來施加取值范圍的約束。
受約束的子類型可以隱式轉(zhuǎn)換為其基本類型,但只有當值不違反子類型的約束時,基本類型才能隱式轉(zhuǎn)換為受約束的子類型。
在一個受約束子類型的變量賦值給另一個受約束子類型的變量時,不僅要滿足隱式轉(zhuǎn)換的要求,還需要滿足目標子類型的各項約束。
以下展示了一些在賦值時不滿足約束條件的示例:
精度約束
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;
顯示結(jié)果如下:
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;
顯示結(jié)果如下:
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;
顯示結(jié)果如下:
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
隱式類型轉(zhuǎn)換
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;
顯示結(jié)果如下:
NOTICE: var2 = 100 ERROR: value too long for type character(3 char) CONTEXT: PL/SQL function inline_code_block line 10 at assignment
子類型作為局部函數(shù)的入?yún)㈩愋秃头祷刂殿愋?/h2>
子類型和其他局部類型一樣,可以作為局部函數(shù)的入?yún)㈩愋秃头祷刂殿愋汀?/p>
示例
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-'); -- 調(diào)用局部函數(shù)inner_func
RAISE NOTICE '%', outer_var;
END;
BEGIN
outer_proc; -- 首先調(diào)用局部過程outer_proc
END;
結(jié)果顯示如下:
NOTICE: outer-inner
DO
由于OUT類型的入?yún)褌魅胱兞砍跏蓟癁镹ULL,因此如果入?yún)㈩愋蜑榫哂蟹强占s束的子類型時,會直接報錯:
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;
顯示結(jié)果如下:
ERROR: null value cannot be assigned to variable "a" declared NOT NULL
CONTEXT: PL/SQL function inline_code_block line 3 at CALL