↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 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 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本。 PostgreSQL 7.3 已结束支持。 请参阅 当前版本手册.

第 7 章 类型转换

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

在很多情况下,用户不需要了解类型转换机制的细节。但 PostgreSQL 所做的隐式转换会影响查询的结果。必要时,用户或程序员可以用显式类型强制转换来定制这些结果。

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

PostgreSQL 程序员指南 中有关于隐式类型转换和强制转换所用确切算法的更多细节。

7.1. 概述 #

SQL 是一种强类型语言。也就是说,每个数据项都有一个相关联的数据类型,它决定了该数据项的行为和允许的用法。PostgreSQL 拥有一个可扩展的类型系统,比其他 SQL 实现更加通用和灵活。因此,PostgreSQL 中大部分类型转换行为应当由一般规则而不是ad hoc(特定)启发式规则支配,以使混合类型表达式即使在有用户定义类型时也有意义。

PostgreSQL 的扫描器/解析器只把词法元素解码成五种基本类别:整数、浮点数、字符串、名字和关键字。大多数扩展类型首先被词法化为字符串。SQL 语言定义允许用字符串指定类型名,这一机制可以在 PostgreSQL 中用来让解析器走上正确的路径。例如,查询

tgl=> 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 表达式整体有已知的输出类型。

许多一般类型转换规则使用了建立在 PostgreSQL 函数和操作符系统表之上的简单约定。转换规则中还包含一些启发式规则,以便更好地支持 SQL 标准固有类型(如 smallint、integer 和 real)的约定。

系统目录存储哪些数据类型之间的转换(称为强制转换)是有效的,以及如何执行这些转换的信息。用户可以用 CREATE CAST 命令添加额外的强制转换。(这通常是结合定义新数据类型来完成的。内置类型之间的强制转换集合经过精心设计,不应当改动。)

解析器中还提供了一个额外的启发式规则,以便对 SQL 标准类型的正确行为做出更好的猜测。定义了几种基本的类型类别:boolean、numeric、string、bitstring、datetime、timespan、geometric、network 以及用户自定义。除用户自定义外,每个类别都有一个在有歧义时会被优先选择的首选类型。在用户自定义类别中,每个类型都是自己的首选类型。有歧义的表达式(有多个候选解析解的表达式)在有多个可能的内置类型时通常可以解决,但在用户定义类型有多个选择时则会报错。

所有类型转换规则的设计都遵循若干原则:

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

  • 解析器没有关于用户定义类型的先验知识,这类类型在类型层次结构中应当处于“更高”的位置。在混合类型的表达式中,原生类型应当总是被转换为用户定义类型(当然,仅在确有必要转换时)。

  • 用户定义的类型之间没有关联。目前,PostgreSQL 没有关于类型之间关系的信息,只有内置类型的硬编码启发式规则以及基于目录中可用函数的隐式关系。

  • 如果查询不需要隐式类型转换,解析器或执行器就不应有额外的开销。也就是说,如果查询构造良好且类型已经匹配,查询就应当继续进行,不必在解析器上花费额外时间,也不必向查询中引入不必要的隐式转换函数。

    此外,如果某个查询通常需要为函数做隐式转换,而之后用户用正确的参数类型定义了一个显式函数,解析器就应使用这个新函数,不再用旧函数做隐式转换。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.