SQL是一种强类型语言。也就是说,每个数据项都有一个关联的数据类型,它决定了该数据项的行为和允许的用法。PostgreSQL 拥有一个可扩展的类型系统,它比其他SQL实现更通用和灵活。因此,PostgreSQL 中的大多数类型转换行为都由通用规则而不是临时启发式方法来管理。这允许混合类型表达式的使用,即使是用户定义的类型。
PostgreSQL 扫描器/解析器将词法元素划分为五个基本类别:整数、非整数数字、字符串、标识符和关键字。大多数非数字类型的常量首先被归类为字符串。SQL语言定义允许指定带有字符串的类型名称,并且可以在 PostgreSQL 中使用此机制来启动解析器走向正确的路径。例如,查询
SELECT text 'Origin' AS "label", point '(0,0)' AS "value"; label | value --------+------- Origin | (0,0) (1 row)
有两个文字常量,类型分别为 text
和 point
。如果未为字符串文字指定类型,则首先分配占位符类型 unknown
,以便在稍后阶段进行解析,如下所述。
在 PostgreSQL 解析器中,有四个基本SQL构造需要不同的类型转换规则
PostgreSQL 类型系统的大部分是围绕一组丰富的函数构建的。函数可以有一个或多个参数。由于 PostgreSQL 允许函数重载,因此仅函数名称不能唯一地标识要调用的函数;解析器必须根据提供的参数的数据类型选择正确的函数。
PostgreSQL 允许使用前缀(单参数)运算符以及中缀(双参数)运算符的表达式。与函数一样,运算符也可以重载,因此存在选择正确运算符的相同问题。
SQL INSERT
和 UPDATE
语句将表达式的结果放入表中。语句中的表达式必须与目标列的类型匹配,并且可能需要转换为目标列的类型。
UNION
、CASE
和相关构造由于联合的 SELECT
语句的所有查询结果都必须出现在一组列中,因此每个 SELECT
子句的结果类型必须匹配并转换为统一的集合。类似地,CASE
构造的结果表达式必须转换为通用类型,以便 CASE
表达式作为一个整体具有已知的输出类型。其他一些构造,例如 ARRAY[]
以及 GREATEST
和 LEAST
函数,也需要确定多个子表达式的公共类型。
系统目录存储有关哪些类型之间存在转换或强制转换的信息,以及如何执行这些转换。用户可以使用 CREATE CAST 命令添加额外的强制转换。(这通常是与定义新数据类型结合使用的。内置类型之间的强制转换集经过精心设计,最好不要更改。)
解析器提供的另一个启发式方法允许改进具有隐式强制转换的类型组之间正确强制转换行为的确定。数据类型分为几个基本类型类别,包括 boolean
、numeric
、string
、bitstring
、datetime
、timespan
、geometric
、network
和用户定义的类型。(有关列表,请参见 表 51.65;但请注意,也可以创建自定义类型类别。)在每个类别中,可以有一个或多个首选类型,当有多种可能类型可供选择时,首选类型会优先使用。通过仔细选择首选类型和可用的隐式强制转换,可以确保以有用的方式解决歧义表达式(具有多个候选解析解决方案的表达式)。
所有类型转换规则的设计都考虑了以下几个原则
隐式转换不应产生令人惊讶或不可预测的结果。
如果查询不需要隐式类型转换,则解析器或执行器中不应有额外的开销。也就是说,如果查询格式良好并且类型已经匹配,则查询应执行而无需在解析器中花费额外的时间,并且无需在查询中引入不必要的隐式转换调用。
此外,如果查询通常需要为函数进行隐式转换,并且如果用户随后定义了具有正确参数类型的新函数,则解析器应使用此新函数,而不再进行隐式转换来使用旧函数。
如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用 此表单 来报告文档问题。