PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Quelle est la règle pour "inconnu" et l'inférence de type ?

Il y a en fait trois questions auxquelles je vais essayer de répondre.

  1. Quel est le but de unknown ?

    Il s'agit du type de données initialement attribué aux valeurs NULL et aux littéraux de chaîne dans les instructions SQL. Si de tels littéraux ont été attribués, tapez text immédiatement, il serait difficile de déduire le type correct.

    Par exemple, vous voulez myfunc('hello') pour invoquer myfunc(character varying) , mais il n'y a pas de conversion de type implicite à partir de text à character varying (et cela créerait une ambiguïté si vous en créiez un).

  2. Pourquoi SELECT null renvoie une colonne de type unknown ?

    La réponse traditionnelle est :parce que l'utilisateur n'a pas spécifié le type.

    Cependant, ce comportement a été problématique. Par exemple, si vous créez un tableau comme celui-ci :

    CREATE TABLE test
       AS SELECT 'hello';
    

    vous vous retrouveriez avec une colonne de type unknown , ce qui n'est pas souhaitable et causera des problèmes par la suite. Le type unknown ne devrait vraiment pas être visible par l'utilisateur, mais plutôt un détail de mise en œuvre.

    Par conséquent, ce commit a changé le comportement à partir de PostgreSQL v10 :Maintenant, tout unknown est laissé dans un SELECT ou RETURNING list sont forcés à text , et les tables ne peuvent pas être créées avec des colonnes de type unknown .

  3. Pourquoi SELECT NULL UNION SELECT 42 fonctionne, mais pas SELECT NULL UNION SELECT NULL UNION SELECT 42 ?

    Cela est dû aux règles de conversion de type .UNION est laissé associatif, donc la dernière requête est interprétée comme

    (SELECT NULL UNION SELECT NULL) UNION SELECT 42;
    

    Maintenant le premier UNION se résout au type de données text à cause de la règle 3 :

    Cela provoque une erreur lors de la tentative de résolution du type pour le deuxième UNION à cause de la règle 4 :

    Par contre, dans la requête

    SELECT NULL UNION SELECT 42;
    

    "NULL" a le type unknown , et "42" est de type integer (le type choisi pour les littéraux numériques sans point décimal).

    Règle 5

    ne s'applique pas ici, car integer n'est pas un type préféré dans sa catégorie (ce serait oid et double precision ), donc la règle 6 est utilisée :

    Cela se traduit par un type de integer .