37.2. PostgreSQL 类型系统

PostgreSQL 数据类型分为基本类型,复合类型,域和伪类型。

37 .2.1. 基本类型

基本类型是像int4这样的类型,它们是在 SQL 语言级别以下实现的(通常以低级语言,例如 C)实现。它们通常对应于通常称为抽象数据类型的内容。 PostgreSQL 只能通过用户提供的功能对这类类型进行操作,并且只能在用户描述它们的范围内理解此类类型的行为。基本类型进一步细分为标量和数组类型。对于每种标量类型,将自动创建一个对应的数组类型,该数组可以容纳该标量类型的可变大小数组。

37 .2.2. 复合类型

每当用户创建表时,都会创建复合类型或行类型。也可以使用CREATE TYPE来定义没有关联表的“独立”组合类型。复合类型只是具有相关字段名称的类型的列表。复合类型的值是字段值的行或记录。用户可以从 SQL 查询访问组件字段。有关组合类型的更多信息,请参考Section 8.16

37.2.3. Domains

域基于特定的基本类型,并且在许多方面都可以与其基本类型互换。但是,域可以具有将其有效值限制为基础基本类型所允许的子集的约束。

可以使用 SQL 命令CREATE DOMAIN创建域。本章不讨论它们的创建和使用。

37.2.4. Pseudo-Types

有一些特殊用途的“伪类型”。伪类型不能显示为表的列或组合类型的属性,但可以用于声明函数的参数和结果类型。这在类型系统中提供了一种机制,可以识别特殊的功能类别。 Table 8.25列出了现有的伪类型。

37 .2.5. 多态类型

五个特别受关注的伪类型是anyelementanyarrayanynonarrayanyenumanyrange,它们统称为多态类型。使用这些类型声明的任何函数都称为多态函数。多态函数可以对许多不同的数据类型进行操作,具体的数据类型由在特定调用中实际传递给它的数据类型确定。

多态参数和结果相互关联,并在解析调用多态函数的查询时将其解析为特定的数据类型。声明为anyelement的每个位置(参数或返回值)都可以具有任何特定的实际数据类型,但是在任何给定的调用中,它们都必须是相同的实际类型。每个声明为anyarray的位置都可以具有任何数组数据类型,但是类似地,它们都必须是同一类型。同样,声明为anyrange的位置必须全部为同一范围类型。此外,如果存在声明为anyarray的位置,而其他声明为anyelement的位置,则anyarray位置中的实际数组类型必须是其元素与anyelement位置中出现的元素相同类型的数组。同样,如果有位置声明为anyrange,其他位置声明为anyelementanyarray,则anyrange位置中的实际范围类型必须是一个范围,该范围的子类型与anyelement位置中出现的类型相同,并且与anyarray位置中的元素类型相同。 anynonarrayanyelement完全相同,但是增加了额外的约束,即实际类型不能为数组类型。 anyenumanyelement完全相同,但是增加了额外的约束,即实际类型必须为枚举类型。

因此,当用一个多态类型声明一个以上的参数位置时,最终的效果是只允许实际参数类型的某些组合。例如,声明为equal(anyelement, anyelement)的函数将采用任意两个 Importing 值,只要它们的数据类型相同即可。

当函数的返回值声明为多态类型时,必须至少有一个也是多态的参数位置,并且作为参数提供的实际数据类型将确定该调用的实际结果类型。例如,如果还没有数组下标机制,则可以将实现下标的函数定义为subscript(anyarray, integer) returns anyelement。该声明将实际的第一个参数约束为数组类型,并允许解析器从实际的第一个参数的类型推断出正确的结果类型。另一个示例是声明为f(anyarray) returns anyenum的函数将仅接受枚举类型的数组。

在大多数情况下,解析器可以从具有不同多态类型的参数中推断出多态结果类型的实际数据类型。例如anyarray可以从anyelement推导出,反之亦然。唯一的 exception 是anyrange类型的多态结果需要anyrange类型的参数;它不能从anyarrayanyelement参数推导出。这是因为可能存在多个具有相同子类型的范围类型。

请注意,anynonarrayanyenum不代表单独的类型变量;它们的类型与anyelement相同,只是有一个附加的约束。例如,将函数声明为f(anyelement, anyenum)等效于将其声明为f(anyenum, anyenum):两个实际参数都必须具有相同的枚举类型。

可变参数函数(如Section 37.4.5那样具有可变数量的参数)可以是多态的:这可以通过将其最后一个参数声明为VARIADIC anyarray来实现。出于参数匹配和确定实际结果类型的目的,该函数的行为与您编写了适当数量的anynonarray参数的行为相同。