10.1. 概述

SQL是一种强类型语言。也就是说,每个数据项都有一个相关的数据类型,数据类型决定其行为和允许的用法。 PostgreSQL有一个可扩展的类型系统,该系统比其它SQL实现更具通用和灵活。因而,PostgreSQL中大多数类型转换行为是由通用规则来管理的,而不是 ad hoc 启发式规则。这种做法允许使用混合类型表达式,即便是其中包含用户定义的类型。

PostgreSQL扫描器/解析器只将词法元素分解成五个基本种类:整数、非整数数字、字符串、标识符、关键字。大多数非数字类型常量首先被分类为字符串。SQL语言定义允许将类型名指定为字符串, 这个机制被PostgreSQL用于保证解析器沿着正确的方向运行。例如,查询:

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

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

有两个文字常量,类型分别为textpoint。如果一个串文字没有指定类型,初始将被分配一个占位符类型unknown,该类型将在下文描述的后续阶段被解析。

在SQL解析器里,有四种基本的SQL结构要求独立的类型转换规则:

函数调用

PostgreSQL类型系统的大部分建立在一套丰富的函数上。 函数可以有一个或多个参数。由于PostgreSQL允许函数重载, 所以函数名自身并不唯一地标识将要被调用的函数,解析器必须根据提供的参数类型选择正确的函数。

操作符

PostgreSQL允许带有前缀和后缀一元(单目)操作符的表达式,也允许二元(两个参数)操作符。像函数一样,操作符也可以被重载,因此操作符的选择也有同样的问题。

值存储

SQL INSERTUPDATE语句将表达式的结果放 入表中。语句中的表达式类型必须和目标列的类型一致(或者可以被转换为一致)。

UNIONCASE和相关结构

因为来自一个联合的SELECT语句中的所有查询结果必须在一个列集中显示,所以每个 SELECT子句的结果类型必须能相互匹配并被转换成一个统一的集合。类似地,一个 CASE结构的结果表达式必须被转换成一种公共的类型,这样CASE表达式作为整体才 有一种已知的输出类型。同样的要求也存在于ARRAY结构以及GREATESTLEAST函数中。

系统目录存储有关哪些数据类型之间存在哪种转换(或 造型 )以及如何执行这些转换的相关信息。额外的造型可以由用户通过CREATE CAST命令增加(这个通常和定义一种新的数据类型一起完成。 内建的类型转换集已经经过了仔细的雕琢,最好不要去更改它们)。

解析器提供了一种额外的启发式规则,它允许在具有隐式造型的类型组中恰当造型行为的改进决定。 数据类型被分为几个基本的 类型分类 ,包括booleannumericstringbitstringdatetimetimespangeometricnetwork和用户自定义(可参阅表 52.63中的列表;但需要注意的是 也可以创建自定义的类型分类)。在每个分类中,可以有一个或多个 首选类型 , 当存在类型选择时,这个是更好的选择。利用精心选择的首选类型和可用的隐式造型, 我们可以确保有歧义的表达式(那些有多个候选解析方案的表达式)可以用一种有用的方式来处理。

所有类型转换规则都是建立在下面几个基本原则上的:

  • 隐式转换决不能有意外的或不可预见的输出。

  • 如果一个查询不需要隐式类型转换,解析器或执行器不应该有额外的开销。也就是说,如果一个查询是结构良好的并且类型已经匹配,则查询不应该在解析器里耗费额外的时间执行,也不会在查询中引入不必要的隐式类型转换调用。

  • 另外,如果一个查询通常要求为某个函数进行隐式类型转换,而用户定义了一个有正确参数类型的新函数, 解析器应该使用新函数并不再做隐式转换来使用旧函数。