PolarDB PostgreSQL版(兼容Oracle)支持用户定义的PL/SQL子类型和(子类型)别名。子类型是具有一组可选约束的数据类型,这些约束限制可以存储在该类型的列中的值。适用于该子类型所基于的类型的规则仍然适用,但您可以使用其他约束限制该类型中存储值的精度或小数位数。

您可以在PL函数、存储过程、匿名块或包的声明中定义子类型。语法如下:

SUBTYPE subtype_name IS type_name[(constraint)] [NOT NULL]

其中constraint为:

{precision [, scale]} | length

其中:

  • subtype_name:subtype_name指定子类型的名称。
  • type_name:type_name指定子类型所基于的原始类型的名称。

    type_name可能是:

    • PolarDB PostgreSQL版(兼容Oracle)支持的任何类型的名称。
    • 任何复合类型的名称。
    • 通过%TYPE运算符固定的列。
    • 另一种子类型的名称。

包括constraint子句以定义支持精度或小数位数的类型的限制。

  • precision:precision指定子类型值中允许的总位数。
  • scale:scale指定子类型值中允许的小数位数。
  • length:length 指定CHARACTER、VARCHAR或TEXT基本类型值中允许的总长度。

包括NOTNULL子句以指定NULL值可不存储在指定子类型的列中。

请注意,基于列的子类型将继承列大小约束,但该子类型不会继承NOT NULL或CHECK约束。

不受约束的子类型

要创建不受约束的子类型,请使用SUBTYPE命令指定新子类型名称和该子类型所基于类型的名称。例如,以下命令会创建一个名为address的子类型,该子类型具有类型CHAR的所有属性:

SUBTYPE address IS CHAR;

您还可以创建另一个子类型的子类型(受约束或不受约束):

SUBTYPE cust_address IS address NOT NULL;

此命令创建名为cust_address的子类型,该子类型共享address子类型的所有属性。包括NOT NULL子句以指定cust_address的值可能并非NULL。

受约束的子类型

基于字符类型创建子类型时包括length值以定义子类型的最大长度。例如:

SUBTYPE acct_name IS VARCHAR (15);

此示例基于VARCHAR数据类型创建名为acct_name的子类型,但限制为15个字符长度。

约束数字基本类型时,包括precision(指定子类型值中的最大位数)和可选的scale(指定小数点右侧的位数)的值。例如:

SUBTYPE acct_balance IS NUMBER (5, 2);

此示例创建名为acct_balance的子类型,该子类型共享NUMBER类型的所有属性,但小数点左侧不得超过3位数,小数点右侧不得超过2位数。

参数声明(在函数或存储过程标头中)为形参。传递给函数或存储过程的值为实参。调用函数或存储过程时,调用方提供(0个或更多)实参。每个实参都分配给一个形参,该形参将值保存在函数或存储过程的主体内。

如果将形参声明为受约束的子类型:

  • 调用函数时,如果将实参分配给形参,则PolarDB PostgreSQL版(兼容Oracle)不会实施子类型约束。
  • 调用过程时,如果将实参分配给形参,则PolarDB PostgreSQL版(兼容Oracle)会实施子类型约束。

使用 %TYPE 运算符

您可以使用%TYPE表示法声明固定到列的子类型。例如:

SUBTYPE emp_type IS emp.empno%TYPE

此命令创建名为emp_type的子类型,其基本类型匹配emp表中empno列的类型。基于列的子类型将共享列大小约束;NOT NULL和CHECK约束不会继承。

子类型转换

不受约束的子类型是其所基于的类型的别名。子类型(不受约束)的任何类型变量都可以与基本类型的变量互换而无需转换,反之亦然。

受约束子类型的变量可以与基本类型的变量互换而无需转换,但基本类型的变量只能在符合子类型约束时与受约束的子类型互换。如果基于相同的子类型,则受约束子类型的变量可以隐式地转换为另一个子类型,并且约束值在其所转换的子类型值范围内。