2017-04-26 66 views
1

我找下面的解释,如果我运行像这样的东西,我得到一个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类型有过一次,如果它认为是在上述情况下的文字?

+0

我投票决定关闭自己的问题,因为我认为这是对[dba.se]更好的匹配 –

+0

我投迁移过,但我不知道它是值得的:这些案件[完美描述在文档](https://www.postgresql.org/docs/current/static/typeconv-union-case.html)(第3点) - 除了最后一个。这只是一个[优先问题](http://rextester.com/TNG47898)。 – pozs

回答

2

其中有三个问题我会尽量回答。

  1. unknown是什么目的?

    这是最初分配给SQL语句中的NULL和字符串文字的数据类型。如果立即将这些文字分配到text类型,则很难推断出正确的类型。

    例如,你想myfunc('hello')调用myfunc(character varying),但是从text没有隐式类型转换为character varying(它会引起歧义,如果你创建了一个)。

  2. 为什么SELECT null返回一个类型为unknown的列?

    传统的答案是:因为用户没有指定类型。

    但是,这种行为一直存在问题。例如,如果您创建一个表是这样的:

    CREATE TABLE test 
        AS SELECT 'hello'; 
    

    你最终会与unknown类型的列,这是不理想的,将进一步对造成问题。 unknown类型确实不应该是用户可见的,而应该是实现细节。

    因此,this commit已经从PostgreSQL的V10改变的行为:现在留在SELECTRETURNING列表中的任何unknown s的被迫text,并表不能与unknown类型的列上创建。

  3. 为什么SELECT NULL UNION SELECT 42有效,但不是SELECT NULL UNION SELECT NULL UNION SELECT 42

    这是欠type conversion rulesUNION是左结合的,因此后者查询被解释为

    (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不在其类别中的首选类型(这将是oiddouble precision),所以第6条用于:

    否则,选择最后的非未知输入类型,允许所有前面的未知输入隐式转换为它。

    这产生integer的一种类型。

+0

假设字符串文本是文本是合理的,但这似乎是一种笨拙的方式。无论如何,好的答案。理想情况下,在结果集完成而不是第一次结合之前,将类型推迟为未知类型会更有意义。 –