PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Qual é a regra para 'desconhecido' e inferência de tipo?


Na verdade, existem três perguntas que vou tentar responder.

  1. Qual é o propósito de unknown ?

    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 tipo text imediatamente, seria difícil inferir o tipo correto.

    Por exemplo, você quer myfunc('hello') para invocar myfunc(character varying) , mas não há conversão de tipo implícito de text para character varying (e causaria ambiguidade se você criasse um).

  2. Por que SELECT null retornar uma coluna do tipo unknown ?

    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 tipo unknown , o que é indesejável e causará problemas mais adiante. O tipo unknown realmente 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 qualquer unknown s deixados em um SELECT ou RETURNING list são forçados a text , e as tabelas não podem ser criadas com colunas do tipo unknown .

  3. Por que SELECT NULL UNION SELECT 42 funciona, mas não SELECT 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 primeiro UNION resolve para o tipo de dados text por causa da regra 3:

    Isso causa um erro ao tentar resolver o tipo para o segundo UNION por causa da regra 4:

    Por outro lado, na consulta
    SELECT NULL UNION SELECT 42;
    

    “NULL” tem o tipo unknown , e "42" tem o tipo integer (o tipo escolhido para literais numéricos sem ponto decimal).

    Regra 5

    não se aplica aqui, porque integer não é um tipo preferido na sua categoria (isso seria oid e double precision ), então a regra 6 é usada:

    Isso resulta em um tipo de integer .