Skip to content

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,以便在稍后的阶段按如下所述进行解析。

有四个基本SQL构造需要在PostgreSQL解析器中使用不同的类型转换规则

函数调用

PostgreSQL 类型系统很大程度上建立在一组丰富的函数之上。函数可以有一个或多个参数。由于 PostgreSQL 允许函数重载,因此函数名称本身并不能唯一标识要调用的函数;解析器必须根据所提供参数的数据类型选择正确的函数。

运算符

PostgreSQL 允许使用前缀(单参数)运算符以及中缀(双参数)运算符的表达式。与函数类似,运算符可以重载,因此存在选择正确运算符的相同问题。

值存储

INSERTUPDATE 语句将表达式的结果放入表中。语句中的表达式必须与目标列的类型匹配,并且可能转换为目标列的类型。

UNIONCASE 和相关构造

由于联合的 SELECT 语句中的所有查询结果必须显示在单列集中,因此必须匹配并转换为统一集每个 SELECT 子句的结果类型。同样,CASE 构造的结果表达式必须转换为通用类型,以便 CASE 表达式作为一个整体具有已知的输出类型。其他一些构造,例如 ARRAY[] 以及 GREATESTLEAST 函数,同样需要确定几个子表达式的通用类型。

系统目录存储有关在哪些数据类型之间存在哪些转换或强制转换的信息,以及如何执行这些转换。用户可以使用CREATE CAST命令添加其他强制转换。(通常与定义新数据类型结合使用。内置类型之间的强制转换集经过精心设计,最好不要更改。)

解析器提供的附加启发式方法允许在具有隐式强制转换的类型组之间改进适当强制转换行为的确定。数据类型分为几个基本类型类别,包括booleannumericstringbitstringdatetimetimespangeometricnetwork和用户定义。(有关列表,请参见表 53.65;但请注意,也可以创建自定义类型类别。)在每个类别中可以有一个或多个首选类型,当有多种可能的类型可供选择时,首选这些类型。通过仔细选择首选类型和可用的隐式强制转换,可以确保以有用的方式解析歧义表达式(具有多个候选解析解决方案的表达式)。

所有类型转换规则的设计都考虑了几个原则

  • 隐式转换永远不应产生令人惊讶或不可预测的结果。

  • 如果查询不需要隐式类型转换,则解析器或执行器中不应该有额外的开销。也就是说,如果查询格式正确且类型已经匹配,则查询应该执行,而无需在解析器中花费额外时间,也无需在查询中引入不必要的隐式转换调用。

  • 此外,如果查询通常需要对函数进行隐式转换,并且如果用户随后使用正确的参数类型定义新函数,则解析器应使用此新函数,不再对旧函数进行隐式转换。