pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
目录
SQL 查询可能有意或无意地要求在同一表达式中混用 不同的数据类型。 Postgres 提供了丰富的机制来 求值混合类型表达式。
在很多情况下,用户不需要了解类型转换机制的 细节。但 Postgres 所做的隐式转换会影响查询的表面结果,用户或程序员可以 用显式类型强制转换来定制 这些结果。
本章介绍 Postgres 的类型转换机制和约定。 关于特定数据类型及允许的函数和 操作符的更多信息,请参阅用户指南和程序员指南中的 相关章节。
程序员指南中有关于隐式类型转换和强制转换所用 确切算法的更多细节。
SQL 是一种强类型语言。也就是说,每个数据项 都有一个相关联的数据类型,它决定了该数据项的行为和允许的用法。 Postgres 拥有一个可扩展的类型系统, 比其他 RDBMS 实现更加通用和灵活。 因此,Postgres 中大部分类型转换行为 应当由一般规则而不是 ad-hoc(特定)启发式规则支配, 以使混合类型表达式即使在有用户定义类型时也有 意义。
Postgres 的扫描器/解析器只把词法元素 解码成五种基本类别:整数、浮点数、字符串、名字和关键字。 大多数扩展类型首先被词法化为字符串。SQL 语言定义允许用字符串指定类型名,这一机制被 Postgres 用来让解析器走上正确的路径。例如,查询
tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value"; Label |Value ------+----- Origin|(0,0) (1 row)
中有两个字符串,类型分别为 text 和 point。 如果没有指定类型,则最初会赋予占位类型 unknown, 并在后面阶段按如下所述解析。
在 Postgres 解析器中有四种基本的 SQL 结构需要 专门的类型转换规则:
Postgres 允许带左一元和右一元(单参数) 操作符的表达式, 也允许二元(双参数)操作符的表达式。
Postgres 类型系统的很大一部分是围绕一套 丰富的函数构建的。函数调用有一个或多个参数,对任何具体的 查询,这些参数都必须与系统目录中可用的函数 匹配。
SQL 的 INSERT 语句把查询的 结果放到表中。查询中的 表达式必须与插入的目标列匹配,必要时还要转换成目标列的 类型。
由于 UNION SELECT 语句的所有查询结果必须出现在一组列中,每个 SELECT 子句的类型必须匹配并转换成统一的 集合。
许多一般类型转换规则使用了建立在 Postgres 函数和操作符系统表之上的简单约定。 转换规则中还包含一些启发式规则,以便更好地支持 SQL92 标准固有类型(如 smallint、integer 和 float)的 约定。
Postgres 解析器使用的约定是:所有 类型转换函数都接受一个源类型的参数,并且以 目标类型的名称命名。满足这一 标准的任何函数都被认为是有效的转换函数,解析器 可以把它当作转换函数使用。这个简单的假设使解析器 无需硬编码就能探索类型转换的可能性, 让扩展的用户定义类型透明地使用这些 相同的特性。
解析器中还提供了一个额外的启发式规则,以便对 SQL 标准类型的正确行为做出更好的猜测。定义了 五种类型类别:boolean、string、numeric、geometric 和用户自定义。除用户自定义外,每个类别都有一个 用于解决候选歧义的"首选类型"。 每个"用户自定义"类型都是自己的"首选类型",因此只含一个 用户定义类型的有歧义表达式(有多个候选解析解的 表达式)可以解析出单一的最佳选择,而含多个 用户定义类型的表达式仍会有歧义并 报错。
候选解只落在一个类型类别内的有歧义表达式 很可能得到解析,而候选跨越多个 类别的有歧义表达式则很可能报错并请求用户 澄清。
所有类型转换规则的设计都考虑了以下几条原则:
隐式转换绝不应有令人意外或不可预测的结果。
解析器没有先验知识的用户定义类型在类型 层级中应该更"高"。在混合类型表达式中,固有类型总是 应当转换成用户定义类型(当然,只在需要转换时 如此)。
用户定义的类型之间没有关联。目前,Postgres 没有关于类型之间关系的信息,只有内置类型的硬编码 启发式规则以及基于目录中可用函数的 隐式关系。
如果查询不需要隐式类型转换,解析器或执行器就不应 有额外的开销。 也就是说,如果查询构造良好且类型已经匹配,查询就应当 继续进行,不必在解析器上花费额外时间,也不必向查询中 引入不必要的隐式转换 函数。
此外,如果某个查询通常需要为函数做隐式转换,而 之后用户用正确的参数类型定义了一个显式函数,解析器 就应使用这个新函数,不再用旧函数做 隐式转换。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。