Estoy buscando una explicación de lo siguiente, si ejecuto algo como esto, obtengo un tipo unknown ,
SELECT pg_typeof(a) FROM ( SELECT null ) AS t(a); pg_typeof ----------- unknown (1 row) Sin embargo, con más complejidad se convierte en text mágicamente,
SELECT pg_typeof(a) FROM ( SELECT null UNION SELECT null ) AS t(a); pg_typeof ----------- text (1 row) La transmisión explícita no cambia eso, esto también devuelve text ,
SELECT pg_typeof(a) FROM ( SELECT null::unknown UNION SELECT null::unknown ) AS t(a);Resulta divertido que esto funciona,
SELECT pg_typeof(a) FROM ( SELECT null UNION SELECT 42 ) AS t(a);Pero esto no,
SELECT pg_typeof(a) FROM ( SELECT null UNION SELECT null UNION SELECT 42 ) AS t(a); ¿Qué propósito tiene el tipo unknown si se supone que es texto en la circunstancia anterior?
En realidad, hay tres preguntas que trataré de responder.
¿Cuál es el propósito de unknown ?
Este es el tipo de datos asignado inicialmente a NULL y literales de cadena en declaraciones SQL. Si a tales literales se les asignara el tipo de text inmediatamente, sería difícil inferir el tipo correcto.
Por ejemplo, quiere que myfunc('hello') invoque myfunc(character varying) , pero no hay conversión de tipos implícita de text a character varying (y causaría ambigüedad si creara uno).
¿Por qué SELECT null devuelve una columna de tipo unknown ?
La respuesta tradicional es: porque el usuario no especificó el tipo.
Sin embargo, este comportamiento ha sido problemático. Por ejemplo, si crea una tabla como esta:
CREATE TABLE test AS SELECT 'hello'; terminaría con una columna de tipo unknown , que no es deseable y causará problemas más adelante. El tipo unknown realmente no debería ser visible para el usuario, sino más bien un detalle de implementación.
En consecuencia, esta confirmación ha cambiado el comportamiento de PostgreSQL v10 en adelante: ahora cualquier correo electrónico unknown que quede en una lista SELECT o RETURNING se fuerza a text y las tablas no se pueden crear con columnas de tipo unknown .
¿Por qué funciona SELECT NULL UNION SELECT 42 , pero no SELECT NULL UNION SELECT NULL UNION SELECT 42 ?
Esto se debe a las reglas de conversión de tipos . UNION se deja asociativa, por lo que la última consulta se interpreta como
(SELECT NULL UNION SELECT NULL) UNION SELECT 42; Ahora, la primera UNION se resuelve en text de tipo de datos debido a la regla 3:
Si todas las entradas son de tipo desconocido, resuelva como tipo texto (el tipo preferido de la categoría de cadena).
Esto provoca un error al intentar resolver el tipo de la segunda UNION debido a la regla 4:
Si las entradas no desconocidas no son todas de la misma categoría de tipo, falla.
Por otro lado, en la consulta
SELECT NULL UNION SELECT 42; "NULL" tiene un tipo unknown y "42" tiene un tipo integer (el tipo elegido para literales numéricos sin punto decimal).
Regla 5
Elija el primer tipo de entrada no desconocido que sea un tipo preferido en esa categoría, si existe.
no se aplica aquí, porque el integer no es un tipo preferido en su categoría (que sería oid y double precision ), por lo que se usa la regla 6:
De lo contrario, elija el último tipo de entrada no desconocido que permita convertir implícitamente todas las entradas anteriores no desconocidas.
Esto da como resultado un tipo de integer .