Consulta para devolver nombres de columnas de salida y tipos de datos de una consulta, tabla o vista


21

¿Existe una consulta o comando de PostgreSQL que devuelve los nombres de campo y los tipos de campo de una consulta, tabla o vista?

Por ejemplo, una solución si se aplica a una consulta SELECT simple como SELECT * from persondebería devolver una lista como:

Column Name   | Column Type
===========================
First Name    | character
Last Name     | character
Age           | integer
Date of Birth | date

He buscado las information_schemavistas descritas en una respuesta a continuación y parece cubrir bastante bien las tablas, y sospecho que también cubre las vistas, pero aún no lo he comprobado.

La última es arbitraria, sino que cualquier válido por ejemplo, consulta SELECT que implica, JOINS, UNIONSetc, en la base de datos. ¿Existe un procedimiento incorporado u otro procedimiento almacenado o secuencia de comandos que pueda devolver lo mismo para cualquier CONSULTA válida?

Estoy desarrollando un programa que crea datos y formularios de consulta y la información es necesaria para la validación de datos y la ejecución de funciones en los datos devueltos.


Obviamente, no existe un solo "comando", pero hay varias formas de recuperar información de los catálogos del sistema. Haga una pregunta específica , agregue un ejemplo y lo que espera a cambio, y denos una idea sobre la intención detrás de esto.
Erwin Brandstetter

1
La razón de la simplicidad es que, en lo que respecta a los clientes SELECT, las consultas, es decir, consultas, es decir, consultas que no definen datos o manipulan datos, ya sea en tablas, vistas u otras consultas, devuelven filas y columnas de datos, por lo que PostgreSQL debería poder devolver un lista de los nombres de columna y sus tipos de datos. Las information_schemavistas mencionadas a continuación en las respuestas parecen responder a las tablas y vistas. Las consultas arbitrarias SELECT son la frontera final.
Editaré

Respuestas:


22

Esquema de información vs. catálogos del sistema

Hemos tenido discusiones sobre esto muchas veces. El esquema de información sirve para ciertos propósitos. Si conoce los catálogos del sistema, estos sirven mejor para la mayoría de los propósitos , IMO. Los catálogos del sistema son la fuente real de toda la información.

El esquema de información proporciona vistas estandarizadas que ayudan con la portabilidad, principalmente en las principales versiones de Postgres, porque la portabilidad en diferentes plataformas RDBMS generalmente es una ilusión una vez que sus consultas son lo suficientemente sofisticadas como para necesitar buscar catálogos de sistemas. Y, en particular, Oracle todavía no es compatible con el esquema de información.

Las vistas en el esquema de información deben saltar a través de muchos aros para lograr un formato que cumpla con el estándar. Esto los hace lentos, a veces muy lentos. Compare los planes y el rendimiento de estos objetos básicos:

EXPLAIN ANALYZE SELECT * from information_schema.columns;
EXPLAIN ANALYZE SELECT * from pg_catalog.pg_attribute;

La diferencia es notable. Realmente depende de lo que estés buscando.

Su ejemplo

Para su ejemplo SELECT * from tbl, compare las dos consultas a continuación para esta tabla simple:

CREATE TEMP TABLE foo(
   A numeric(12,3)
 , b timestamp(0)
);

Utilizando pg_attribute:

SELECT attname, format_type(atttypid, atttypmod) AS type
FROM   pg_attribute
WHERE  attrelid = 'foo'::regclass
AND    attnum > 0
AND    NOT attisdropped
ORDER  BY attnum;

format_type() devuelve el tipo completo con todos los modificadores:

attname | type
--------+-------------------------------
a       | numeric(12,3)
b       | timestamp(0) without time zone

También tenga en cuenta que el reparto para regclassresuelve el nombre de la tabla de manera algo inteligente de acuerdo con el actual search_path. También genera una excepción si el nombre no es válido. Detalles:

Utilizando information_schema.columns:

SELECT column_name, data_type
FROM   information_schema.columns
WHERE  table_name = 'foo'
ORDER  BY ordinal_position;

La información está estandarizada, pero incompleta :

column_name | data_type
------------+----------------------------
a           | numeric
b           | timestamp without time zone

Para obtener información completa sobre el tipo de datos, debe considerar todas estas columnas además:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Respuestas relacionadas:

Una lista de pros y contras , los mayores pros (IMO) en negrita:

Vistas del esquema de información

  • a menudo más simple (depende)
  • lento
  • preprocesado, que puede o no satisfacer sus necesidades
  • selectiva (los usuarios solo ven los objetos para los que tienen privilegios)
  • conforme a un estándar SQL (implementado por algunos de los principales RDBMS)
  • mayormente portátil en las principales versiones de Postgres
  • no requieren mucho conocimiento específico sobre Postgres
  • los identificadores son descriptivos, largos y a veces incómodos

Catálogos del sistema

  • a menudo más complejo (depende), más cerca de la fuente
  • rápido
  • completo (columnas del sistema como oidincluidas)
  • no cumple con un estándar SQL
  • menos portátil en las principales versiones de Postgres (pero lo básico no va a cambiar)
  • requieren un conocimiento más específico sobre Postgres
  • los identificadores son concisos, menos descriptivos pero convenientemente cortos

Consulta arbitraria

Para obtener la misma lista de nombres y tipos de columnas de una consulta, puede usar un simple truco: CREAR una tabla temporal a partir de la salida de la consulta, luego use las mismas técnicas que anteriormente.

Puede agregar LIMIT 0, ya que no necesita datos reales:

CREATE TEMP TABLE tmp123 AS
SELECT 1::numeric, now()
LIMIT  0;

Para obtener el tipo de datos de columnas individuales, también puede usar la función pg_typeof():

SELECT pg_typeof(1);

Muchas gracias. He estado buscando cómo obtener el tipo de datos de la columna en pg_attribute por un tiempo y acabo de encontrar esta publicación. Agradezco tu publicación.
Melinda

Esto es útil en general, pero no responde la pregunta original sobre cómo obtener información sobre los tipos de datos de las columnas que entrega una instrucción SELECT. No se trataba de las columnas de vistas o tablas, que por supuesto residen en los catálogos del sistema y también se muestran en el esquema de información.
Holger Jakobs


2

Si tiene acceso al pg_catalog y usa PgAdmin3, le recomiendo una solución que encontré en el blog de Valentine's Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields. html ) Es una macro PgAdmin3 a la que se puede acceder con un acceso directo para mostrar la definición de un nombre de tabla seleccionado.

select quote_ident(nspname) || '.' || quote_ident(relname) as table_name, 
       quote_ident(attname) as field_name, 
       format_type(atttypid,atttypmod) as field_type, 
       case when attnotnull then ' NOT NULL' else '' end as null_constraint,
       case when atthasdef then 'DEFAULT ' || 
                                ( select pg_get_expr(adbin, attrelid) 
                                    from pg_attrdef 
                                   where adrelid = attrelid and adnum = attnum )::text else ''
       end as dafault_value,
       case when nullif(confrelid, 0) is not null
            then confrelid::regclass::text || '( ' || 
                 array_to_string( ARRAY( select quote_ident( fa.attname ) 
                                           from pg_attribute as fa 
                                          where fa.attnum = ANY ( confkey ) 
                                            and fa.attrelid = confrelid
                                          order by fa.attnum 
                                        ), ','
                                 ) || ' )'
            else '' end as references_to
  from pg_attribute 
       left outer join pg_constraint on conrelid = attrelid 
                                    and attnum = conkey[1] 
                                    and array_upper( conkey, 1 ) = 1,
       pg_class, 
       pg_namespace
 where pg_class.oid = attrelid
   and pg_namespace.oid = relnamespace
   and pg_class.oid = btrim( '$SELECTION$' )::regclass::oid
   and attnum > 0
   and not attisdropped
 order by attrelid, attnum;

Funciona como un encanto y extremadamente útil.


1

Use las information_schemavistas , son estándar SQL y contienen la información que desea.

Usted puede también directamente el acceso pg_class, pg_attributeetc, pero eso es no portables y con frecuencia fiddlier; es posible que tenga funciones de ayuda comooidvectortypes , pg_get_function_arguments, etc para algunas cosas.

Si desea ver cómo se psqlejecuta algo así \dt, ejecute psql -E: imprimirá la consulta. Sin embargo, generalmente es mejor usar el information_schemasi satisface sus necesidades.


1

Esto puede ser demasiado simple, pero pgAdmin4 muestra los tipos de campo en los resultados de salida. Las otras soluciones anteriores son probablemente más elegantes, pero cuando solo necesito una respuesta rápida, encuentro que la GUI de consulta de pgAdmin4 funciona bastante bien. Intentar averiguar el tipo de campo de un campo calculado devuelto por una vista o función puede ser complicado.

ingrese la descripción de la imagen aquí


Es muy bueno que pgAdmin4 haga esto, pero ¿cómo lo hace? ¿Podemos averiguarlo sin escanear todo el código fuente de PgAdmin4?
Holger Jakobs
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.