“未知”和类型推断的规则是什么?
我找下面的解释,如果我运行像这样的东西,我得到一个unknown
类型,“未知”和类型推断的规则是什么?
SELECT pg_typeof(a)
FROM (SELECT null) AS t(a);
pg_typeof
-----------
unknown
(1 row)
然而,随着更多的复杂性就变得text
神奇,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT null
) AS t(a);
pg_typeof
-----------
text
(1 row)
明确铸造没有改变,这也返回text
,
SELECT pg_typeof(a)
FROM (
SELECT null::unknown
UNION SELECT null::unknown
) AS t(a);
它是如下usingly这个工作,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT 42
) AS t(a);
但是,这不,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT null
UNION SELECT 42
) AS t(a);
什么用途的unknown
类型有过一次,如果它认为是在上述情况下的文字?
其中有三个问题我会尽量回答。
-
unknown
是什么目的?这是最初分配给SQL语句中的NULL和字符串文字的数据类型。如果立即将这些文字分配到
text
类型,则很难推断出正确的类型。例如,你想
myfunc('hello')
调用myfunc(character varying)
,但是从text
没有隐式类型转换为character varying
(它会引起歧义,如果你创建了一个)。 -
为什么
SELECT null
返回一个类型为unknown
的列?传统的答案是:因为用户没有指定类型。
但是,这种行为一直存在问题。例如,如果您创建一个表是这样的:
CREATE TABLE test AS SELECT 'hello';
你最终会与
unknown
类型的列,这是不理想的,将进一步对造成问题。unknown
类型确实不应该是用户可见的,而应该是实现细节。因此,this commit已经从PostgreSQL的V10改变的行为:现在留在
SELECT
或RETURNING
列表中的任何unknown
s的被迫text
,并表不能与unknown
类型的列上创建。 -
为什么
SELECT NULL UNION SELECT 42
有效,但不是SELECT NULL UNION SELECT NULL UNION SELECT 42
?这是欠type conversion rules。
UNION
是左结合的,因此后者查询被解释为(SELECT NULL UNION SELECT NULL) UNION SELECT 42;
现在第一
UNION
解析为text
因为规则3的数据类型:如果所有输入都是类型unknown,解析为键入文本(字符串类别的首选类型)。
这将导致试图解决型第二
UNION
因为规则4时的错误:如果非unknown输入不是全部属于同一类型类别,失败。
在另一方面,在查询
SELECT NULL UNION SELECT 42;
“ ” NULL已键入
unknown
,和“ ” 42具有类型integer
(选择用于数字文字不带小数点的类型)。规则5
选择第一非未知输入类型,是在该类别中的优选类型,如果有的话。
在这里并不适用,因为
integer
不在其类别中的首选类型(这将是oid
和double precision
),所以第6条用于:否则,选择最后的非未知输入类型,允许所有前面的未知输入隐式转换为它。
这产生
integer
的一种类型。
假设字符串文本是文本是合理的,但这似乎是一种笨拙的方式。无论如何,好的答案。理想情况下,在结果集完成而不是第一次结合之前,将类型推迟为未知类型会更有意义。 –
我投票决定关闭自己的问题,因为我认为这是对[dba.se]更好的匹配 –
我投迁移过,但我不知道它是值得的:这些案件[完美描述在文档](https://www.postgresql.org/docs/current/static/typeconv-union-case.html)(第3点) - 除了最后一个。这只是一个[优先问题](http://rextester.com/TNG47898)。 – pozs