受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

Chapter 10. 类型转换

SQL语句可能有意或无意地要求在同一表达式中混用不同的数据类型。PostgreSQL提供了丰富的机制来求值这类混合类型表达式。

在很多情况下,用户并不需要理解类型转换机制的细节。不过,PostgreSQL执行的隐式类型转换会影响查询结果。必要时,可以使用显式类型转换来控制这些结果。

本章介绍PostgreSQL的类型转换机制和约定。有关特定数据类型以及允许使用的函数和操作符的更多信息,请参阅Chapter 8Chapter 9中的相关章节。

10.1. 概述 #

SQL是一种强类型语言。也就是说,每个数据项都关联着一个决定其行为和允许用法的数据类型。PostgreSQL拥有可扩展的类型系统,比其他SQL实现更通用也更灵活。因此,PostgreSQL中的大多数类型转换行为都由通用规则控制,而不是依赖临时性的启发式规则。这使得即使表达式中包含用户定义类型,也能够使用混合类型表达式。

PostgreSQL扫描器/解析器将词法元素分成五个基本类别:整数、非整数数字、字符串、标识符和关键字。大多数非数值类型的常量会先被归类为字符串。SQL语言定义允许用字符串指定类型名,而PostgreSQL可以利用这一机制让解析器从一开始就沿着正确的路径处理。例如,查询:

SELECT text 'Origin' AS "label", point '(0,0)' AS "value";

 label  | value
--------+-------
 Origin | (0,0)
(1 row)

包含两个文字常量,它们的类型分别是textpoint。如果没有为某个字符串文字指定类型,那么它最初会被赋予占位类型unknown,并在后文所述的后续阶段解析。

PostgreSQL解析器中,有四种基本的SQL结构需要采用不同的类型转换规则:

函数调用 #

PostgreSQL类型系统的很大一部分建立在一套丰富的函数之上。函数可以有一个或多个参数。由于PostgreSQL支持函数重载,单凭函数名无法唯一确定要调用哪个函数;解析器必须根据所提供参数的数据类型选择正确的函数。

操作符 #

PostgreSQL允许使用前缀(一元)操作符和中缀(二元)操作符。与函数一样,操作符也可以重载,因此同样存在选择正确操作符的问题。

值存储 #

SQLINSERTUPDATE语句会把表达式的结果放入表中。语句中的表达式必须与目标列的类型匹配,并且在必要时转换为目标列类型。

UNIONCASE和相关结构 #

由于经UNION合并的SELECT语句的所有查询结果都必须出现在同一组列中,因此每个SELECT子句的结果类型必须彼此匹配,并转换为统一的一组类型。类似地,CASE结构中的结果表达式必须转换为某种公共类型,这样整个CASE表达式才有确定的输出类型。其他一些结构,如ARRAY[]以及GREATESTLEAST函数,也同样需要为若干子表达式确定公共类型。

系统目录保存了哪些数据类型之间存在哪些类型转换,以及如何执行这些转换的信息。用户还可以使用CREATE CAST命令添加额外的类型转换。(这通常与定义新数据类型一并完成。内置类型之间的类型转换集合经过精心设计,最好不要改动。)

解析器还提供了一种额外的启发式规则,可在存在隐式类型转换的一组类型之间更准确地判定适当的转换行为。数据类型被划分为若干基本的类型分类,包括booleannumericstringbitstringdatetimetimespangeometricnetwork以及用户定义类型。(列表见Table 50.63;不过也可以创建自定义类型分类。)每个分类中可以有一个或多个首选类型,当存在多种可能类型可选时,会优先选择它们。通过仔细选择首选类型和可用的隐式类型转换,可以确保有歧义的表达式(即存在多个候选解析方案的表达式)能够以有用的方式被解析。

所有类型转换规则都以以下几个原则为基础:

  • 隐式转换绝不应产生令人意外或无法预测的结果。

  • 如果查询不需要隐式类型转换,解析器和执行器就不应承担额外开销。也就是说,如果查询本身书写正确且类型已经匹配,那么执行时不应让解析器额外耗时,也不应在查询中引入不必要的隐式类型转换调用。

  • 此外,如果某个查询通常需要先对参数做隐式类型转换才能调用某个函数,而此后用户又定义了一个参数类型正确的新函数,那么解析器应改为使用这个新函数,而不再通过隐式转换去调用旧函数。

提交更正

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