问题
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 - textimmediately, it would be difficult to infer the correct type.- For example, you want - myfunc('hello')to invoke- myfunc(character varying), but there is no implicit type cast from- textto- character varying(and it would cause ambiguity if you created one).
- Why does - SELECT nullreturn a column of type- unknown?- 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 type- unknownreally should not be user visible, but rather an implementation detail.- Consequently, this commit has changed the behaviour from PostgreSQL v10 on: Now any - unknowns left in a- SELECTor- RETURNINGlist are forced to- text, and tables cannot be created with columns of type- unknown.
- Why does - SELECT NULL UNION SELECT 42work, but not- SELECT NULL UNION SELECT NULL UNION SELECT 42?- This is owed to the type conversion rules. - UNIONis left associative, so the latter query is interpreted as- (SELECT NULL UNION SELECT NULL) UNION SELECT 42;- Now the first - UNIONresolves to data type- textbecause 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 - UNIONbecause 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 type- integer(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 - integeris not a preferred type in its category (that would be- oidand- double 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