2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4

36.2. PostgreSQL 类型系统 #

PostgreSQL 数据类型可分为基本类型、容器类型、域和伪类型。

36.2.1. 基本类型 #

基本类型是指那些在语言(通常是像 C 这样的底层语言)的底层实现的类型,例如 integerSQL它们通常对应于常被称为抽象数据类型的类型。PostgreSQL 只能通过用户提供的函数来操作这些类型,并且只理解用户描述的这些类型的行为。内置的基本类型在 第 8 章 中进行了描述。

枚举(enum)类型可以被视为基本类型的一个子类。主要区别在于它们可以使用简单的SQL命令创建,而无需任何底层编程。有关更多信息,请参阅 8.7 节

36.2.2. 容器类型 #

PostgreSQL 有三种“容器”类型,它们是包含多个其他类型值的类型。这些是数组、复合类型和范围类型。

数组可以包含所有相同类型的多个值。对于每种基本类型、复合类型、范围类型和域类型,都会自动创建一个数组类型。但是没有数组的数组。就类型系统而言,多维数组与一维数组相同。有关更多信息,请参阅 8.15 节

复合类型,或行类型,是在用户创建表时创建的。也可以使用 CREATE TYPE 来定义一个没有关联表的“独立”复合类型。复合类型只是一个包含关联字段名的类型列表。复合类型的值是字段值的行或记录。有关更多信息,请参阅 8.16 节

范围类型可以包含同一类型的两个值,它们是范围的下限和上限。范围类型是用户创建的,尽管存在一些内置的范围类型。有关更多信息,请参阅 8.17 节

36.2.3. 域 #

域基于特定的底层类型,并且在许多用途上与其底层类型可互换。但是,域可以具有限制其有效值范围的约束,使其成为底层类型允许范围的子集。域使用SQL命令 CREATE DOMAIN 创建。有关更多信息,请参阅 8.18 节

36.2.4. 伪类型 #

有一些用于特殊目的的“伪类型”。伪类型不能作为表列或容器类型的组件出现,但它们可以用于声明函数的参数和返回类型。这在类型系统中提供了一种机制来标识函数的特殊类别。表 8.27 列出了现有的伪类型。

36.2.5. 多态类型 #

一些特别有趣的伪类型是多态类型,它们用于声明多态函数。这一强大功能允许单个函数定义操作多种不同的数据类型,其中具体数据类型在特定调用中通过传递给它的实际数据类型来确定。多态类型显示在 表 36.1 中。一些使用示例出现在 36.5.11 节

表 36.1. 多态类型

名称 描述
anyelement 简单 表示函数接受任何数据类型
anyarray 简单 表示函数接受任何数组数据类型
anynonarray 简单 表示函数接受任何非数组数据类型
anyenum 简单 表示函数接受任何枚举数据类型(参见 8.7 节
anyrange 简单 表示函数接受任何范围数据类型(参见 8.17 节
anymultirange 简单 表示函数接受任何多范围数据类型(参见 8.17 节
anycompatible 通用 表示函数接受任何数据类型,并自动将多个参数提升到通用数据类型
anycompatiblearray 通用 表示函数接受任何数组数据类型,并自动将多个参数提升到通用数据类型
anycompatiblenonarray 通用 表示函数接受任何非数组数据类型,并自动将多个参数提升到通用数据类型
anycompatiblerange 通用 表示函数接受任何范围数据类型,并自动将多个参数提升到通用数据类型
anycompatiblemultirange 通用 表示函数接受任何多范围数据类型,并自动将多个参数提升到通用数据类型

多态参数和结果相互关联,并在解析调用多态函数的查询时解析为特定数据类型。当存在多个多态参数时,输入值的实际数据类型必须匹配,如下所述。如果函数的返回类型是多态的,或者它具有多态类型的输出参数,则这些结果的类型将根据下面描述的多态输入值类型进行推断。

对于“简单”多态类型族,匹配和推断规则如下:

声明为 anyelement 的每个位置(参数或返回值)都可以具有任何特定的实际数据类型,但在任何给定的调用中,它们都必须是相同的实际类型。声明为 anyarray 的每个位置都可以是任何数组数据类型,但同样它们必须是相同的类型。同样,声明为 anyrange 的位置必须是相同的范围类型。 anymultirange 也是如此。

此外,如果存在声明为 anyarray 的位置而其他位置声明为 anyelement,则 anyarray 位置中的实际数组类型必须是其元素类型与 anyelement 位置中出现的类型相同的数组。anynonarray 的处理方式与 anyelement 完全相同,但增加了额外的约束,即实际类型不能是数组类型。anyenum 的处理方式与 anyelement 完全相同,但增加了额外的约束,即实际类型必须是枚举类型。

同样,如果存在声明为 anyrange 的位置而其他位置声明为 anyelementanyarray,则 anyrange 位置中的实际范围类型必须是其子类型与 anyelement 位置中出现的类型相同,并且与 anyarray 位置中的元素类型相同的范围。anymultirange 的声明如果存在,其实际多范围类型必须包含与声明为 anyrange 的参数匹配的范围,以及与声明为 anyelementanyarray 的参数匹配的基本元素。

因此,当一个函数声明了多个多态类型参数时,其净效应是只允许某些实际参数类型的组合。例如,声明为 equal(anyelement, anyelement) 的函数将接受任意两个输入值,只要它们是相同数据类型即可。

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

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

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

对于“通用”多态类型族,匹配和推断规则与“简单”族大致相同,但有一个主要区别:参数的实际类型不必完全相同,只要它们可以隐式转换为一个通用的单一类型即可。通用类型的选择遵循与 UNION 和相关构造相同的规则(参见 10.5 节)。通用类型的选择考虑了 anycompatibleanycompatiblenonarray 输入的实际类型, anycompatiblearray 输入的数组元素类型, anycompatiblerange 输入的范围子类型,以及 anycompatiblemultirange 输入的多范围子类型。如果存在 anycompatiblenonarray,则通用类型必须是非数组类型。一旦确定了通用类型, anycompatibleanycompatiblenonarray 位置的参数将自动转换为该类型,而 anycompatiblearray 位置的参数将自动转换为该类型的数组类型。

由于无法仅通过子类型选择范围类型,因此使用 anycompatiblerange 和/或 anycompatiblemultirange 要求声明具有该类型的参数必须具有相同的实际范围和/或多范围类型,并且该类型的子类型与选定的通用类型一致,从而不需要转换范围值。与 anyrangeanymultirange 一样,将 anycompatiblerangeanycompatiblemultirange 用作函数结果类型要求存在 anycompatiblerangeanycompatiblemultirange 参数。

请注意,没有 anycompatibleenum 类型。这种类型用处不大,因为通常没有到枚举类型的隐式转换,这意味着无法为不相似的枚举输入解析通用类型。

简单”和“通用”多态族代表两个独立类型的变量集。例如,考虑

CREATE FUNCTION myfunc(a anyelement, b anyelement,
                       c anycompatible, d anycompatible)
RETURNS anycompatible AS ...

在此函数的一个实际调用中,前两个输入必须具有完全相同的类型。最后两个输入必须可提升到一个通用类型,但该类型可能与前两个输入的类型无关。结果将具有后两个输入的通用类型。

可变参数函数(接受可变数量参数的函数,如 36.5.6 节)可以是多态的:这是通过将其最后一个参数声明为 VARIADIC anyarrayVARIADIC anycompatiblearray 来实现的。为了进行参数匹配和确定实际结果类型,此类函数与声明适当数量的 anynonarrayanycompatiblenonarray 参数的行为相同。

提交更正

如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步说明的内容,请使用 此表单 报告文档问题。