Na verdade, existem três perguntas que vou tentar responder.
-
Qual é o propósito deunknown?
Este é o tipo de dados inicialmente atribuído a NULLs e literais de string em instruções SQL. Se tais literais foram atribuídos ao tipotextimediatamente, seria difícil inferir o tipo correto.
Por exemplo, você quermyfunc('hello')para invocarmyfunc(character varying), mas não há conversão de tipo implícito detextparacharacter varying(e causaria ambiguidade se você criasse um).
-
Por queSELECT nullretornar uma coluna do tipounknown?
A resposta tradicional é:porque o usuário não especificou o tipo.
No entanto, esse comportamento tem sido problemático. Por exemplo, se você criar uma tabela como esta:
CREATE TABLE test AS SELECT 'hello';
você terminaria com uma coluna do tipounknown, o que é indesejável e causará problemas mais adiante. O tipounknownrealmente não deve ser visível ao usuário, mas sim um detalhe de implementação.
Consequentemente, este commit mudou o comportamento do PostgreSQL v10 em:Agora qualquerunknowns deixados em umSELECTouRETURNINGlist são forçados atext, e as tabelas não podem ser criadas com colunas do tipounknown.
-
Por queSELECT NULL UNION SELECT 42funciona, mas nãoSELECT NULL UNION SELECT NULL UNION SELECT 42?
Isso se deve às regras de conversão de tipo .UNIONé associativo à esquerda, então a última consulta é interpretada como
(SELECT NULL UNION SELECT NULL) UNION SELECT 42;
Agora o primeiroUNIONresolve para o tipo de dadostextpor causa da regra 3:
Isso causa um erro ao tentar resolver o tipo para o segundoUNIONpor causa da regra 4:
Por outro lado, na consulta
SELECT NULL UNION SELECT 42;
“NULL” tem o tipounknown, e "42" tem o tipointeger(o tipo escolhido para literais numéricos sem ponto decimal).
Regra 5
não se aplica aqui, porqueintegernão é um tipo preferido na sua categoria (isso seriaoidedouble precision), então a regra 6 é usada:
Isso resulta em um tipo deinteger.