文档

子类型

更新时间:

本文介绍了自定义子类型的语法及示例等内容。

语法

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_varbase_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
  • 本页导读 (0)
文档反馈