问题
I'm looking for an explanation of the following, If I run something like this I get an unknown
type,
SELECT pg_typeof(a)
FROM ( SELECT null ) AS t(a);
pg_typeof
-----------
unknown
(1 row)
However, with more complexity it becomes text
magically,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT null
) AS t(a);
pg_typeof
-----------
text
(1 row)
Explicit casting doesn't change that, this also returns text
,
SELECT pg_typeof(a)
FROM (
SELECT null::unknown
UNION SELECT null::unknown
) AS t(a);
It follows amusingly that this works,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT 42
) AS t(a);
But this doesn't,
SELECT pg_typeof(a)
FROM (
SELECT null
UNION SELECT null
UNION SELECT 42
) AS t(a);
What purpose does the unknown
type have at all if it's assumed to be text in the above circumstance?
回答1:
There are actually three questions in there that I will try to answer.
What is the purpose of
unknown
?This is the data type initially assigned to NULLs and string literals in SQL statements. If such literals were assigned type
text
immediately, it would be difficult to infer the correct type.For example, you want
myfunc('hello')
to invokemyfunc(character varying)
, but there is no implicit type cast fromtext
tocharacter varying
(and it would cause ambiguity if you created one).Why does
SELECT null
return a column of typeunknown
?The traditional answer is: Because the user didn't specify the type.
However, this behaviour has been problematic. For example, if you create a table like this:
CREATE TABLE test AS SELECT 'hello';
you would end up with a column of type
unknown
, which is undesireable and will cause problems further on. The typeunknown
really should not be user visible, but rather an implementation detail.Consequently, this commit has changed the behaviour from PostgreSQL v10 on: Now any
unknown
s left in aSELECT
orRETURNING
list are forced totext
, and tables cannot be created with columns of typeunknown
.Why does
SELECT NULL UNION SELECT 42
work, but notSELECT NULL UNION SELECT NULL UNION SELECT 42
?This is owed to the type conversion rules.
UNION
is left associative, so the latter query is interpreted as(SELECT NULL UNION SELECT NULL) UNION SELECT 42;
Now the first
UNION
resolves to data typetext
because of rule 3:If all inputs are of type unknown, resolve as type text (the preferred type of the string category).
This causes an error when trying to resolve the type for the second
UNION
because of rule 4:If the non-unknown inputs are not all of the same type category, fail.
On the other hand, in the query
SELECT NULL UNION SELECT 42;
“NULL” has type
unknown
, and “42” has typeinteger
(the type chosen for numeric literals without decimal point).Rule 5
Choose the first non-unknown input type which is a preferred type in that category, if there is one.
does not apply here, because
integer
is not a preferred type in its category (that would beoid
anddouble precision
), so rule 6 is used:Otherwise, choose the last non-unknown input type that allows all the preceding non-unknown inputs to be implicitly converted to it.
This results in a type of
integer
.
来源:https://stackoverflow.com/questions/43624354/what-is-the-rule-for-unknown-and-type-inference