10.5.UNION
、CASE
及相关结构#
SQLUNION
结构必须匹配可能不同的类型才能成为一个结果集。解析算法分别应用于联合查询的每个输出列。INTERSECT
和EXCEPT
结构以与UNION
相同的方式解析不同的类型。包括CASE
、ARRAY
、VALUES
以及GREATEST
和LEAST
函数在内的其他一些结构使用相同的算法来匹配其组件表达式并选择结果数据类型。
UNION
、CASE
及相关结构的类型解析
如果所有输入都属于同一类型,并且它不是
unknown
,则按该类型解析。如果任何输入属于域类型,则在所有后续步骤中将其视为域的基本类型。 [12]
如果所有输入都属于
unknown
类型,则按text
类型解析(字符串类别的首选类型)。否则,在剩余规则中忽略unknown
输入。如果非未知输入不属于同一类型类别,则失败。
选择第一个非未知输入类型作为候选类型,然后从左到右考虑其他非未知输入类型。[13]如果候选类型可以隐式转换为其他类型,但反之不行,则选择其他类型作为新的候选类型。然后继续考虑剩余的输入。如果在此过程的任何阶段选择了首选类型,则停止考虑其他输入。
将所有输入转换为最终的候选类型。如果给定的输入类型无法隐式转换为候选类型,则失败。
以下是一些示例。
示例 10.10. 在联合中使用未指定类型的类型解析
SELECT text 'a' AS "text" UNION SELECT 'b';
text
------
a
b
(2 rows)
此处,未知类型文本'b'
将解析为类型text
。
示例 10.11. 在简单联合中进行类型解析
SELECT 1.2 AS "numeric" UNION SELECT 1;
numeric
---------
1
1.2
(2 rows)
文本1.2
的类型为numeric
,并且integer
值1
可以隐式转换为numeric
,因此使用该类型。
示例 10.12. 在转置联合中进行类型解析
SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL);
real
------
1
2.2
(2 rows)
此处,由于类型real
无法隐式转换为integer
,但integer
可以隐式转换为real
,因此联合结果类型解析为real
。
示例 10.13. 在嵌套联合中进行类型解析
SELECT NULL UNION SELECT NULL UNION SELECT 1;
ERROR: UNION types text and integer cannot be matched
发生此失败是因为PostgreSQL将多个UNION
视为成对操作的嵌套;也就是说,此输入与以下内容相同
(SELECT NULL UNION SELECT NULL) UNION SELECT 1;
根据上述规则,内部UNION
解析为发出类型text
。然后,外部UNION
的输入类型为text
和integer
,导致观察到的错误。可以通过确保最左边的UNION
至少有一个所需结果类型的输入来解决此问题。
INTERSECT
和EXCEPT
操作同样成对解析。然而,本节中描述的其他结构在一步解析中考虑其所有输入。
[12]有点像对运算符和函数的域输入的处理,此行为允许域类型通过UNION
或类似结构保留,只要用户小心确保所有输入隐式或显式地为该确切类型即可。否则将使用域的基本类型。
[13]由于历史原因,CASE
将其ELSE
子句(如果有)视为“first”输入,然后考虑THEN
子句。在所有其他情况下,“left to right”表示表达式在查询文本中出现的顺序。