Query per restituire nomi di colonne di output e tipi di dati di una query, tabella o vista


21

Esiste una query o un comando PostgreSQL che restituisce i nomi e i tipi di campo di una query, tabella o vista?

Ad esempio, una soluzione se applicata a una semplice query SELECT come SELECT * from persondovrebbe restituire un elenco come:

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

Ho cercato le information_schemaviste descritte in una risposta di seguito e sembra coprire abbastanza bene le tabelle, e sospetto che riguardi anche le viste, ma non l'ho ancora verificato.

L'ultima è qualsiasi query SELECT arbitraria ma valida, ad esempio che coinvolge JOINS, UNIONSecc., Nel database. Esiste una procedura integrata o un'altra procedura memorizzata o uno script che può restituire lo stesso per qualsiasi QUERY valida?

Sto sviluppando un programma che crea dati e moduli di query e le informazioni sono necessarie per la convalida dei dati e l'esecuzione di funzioni sui dati restituiti.


Non esiste un singolo "comando", ovviamente, ma ci sono vari modi per recuperare informazioni dai cataloghi di sistema. Per favore, fai una domanda specifica , aggiungi un esempio e cosa ti aspetti in cambio e dacci un'idea dell'intenzione che sta dietro.
Erwin Brandstetter,

1
Il motivo della semplicità è che per quanto riguarda i client query, ovvero SELECTquery, ovvero query di non definizione dei dati o di manipolazione dei dati, sia su tabelle, viste o altre query restituiscono righe e colonne di dati, quindi PostgreSQL dovrebbe essere in grado di restituire un elenco dei nomi delle colonne e dei relativi tipi di dati. Le information_schemaviste menzionate di seguito nelle risposte sembrano rispondere a tabelle e viste. Le query SELECT arbitrarie sono l'ultima frontiera.
Modificherò

Risposte:


22

Schema informativo e cataloghi di sistema

Ne abbiamo discusso molte volte. Lo schema informativo ha determinati scopi. Se conosci i cataloghi di sistema, quelli servono meglio gli scopi , IMO. I cataloghi di sistema sono la vera fonte di tutte le informazioni.

Lo schema informativo fornisce viste standardizzate che aiutano la portabilità, soprattutto nelle principali versioni di Postgres, perché la portabilità su piattaforme RDBMS diverse è in genere un'illusione quando le tue query sono abbastanza sofisticate da richiedere la ricerca di cataloghi di sistema. E, in particolare, Oracle non supporta ancora lo schema delle informazioni.

Le viste nello schema delle informazioni devono passare attraverso molti cerchi per ottenere un formato conforme allo standard. Questo li rende lenti, a volte molto lenti. Confronta piani e prestazioni per questi oggetti di base:

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

La differenza è notevole. Dipende davvero da cosa stai cercando.

Il tuo esempio

Per il tuo esempio SELECT * from tbl, confronta le due query seguenti per questa semplice tabella:

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

Utilizzando 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() restituisce il tipo completo con tutti i modificatori:

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

Si noti inoltre che il cast regclassrisolve il nome della tabella in modo un po 'intelligente in base alla corrente search_path. Inoltre genera un'eccezione se il nome non è valido. Dettagli:

Utilizzando information_schema.columns:

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

Le informazioni sono standardizzate, ma incomplete :

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

Per ottenere informazioni complete per il tipo di dati, è necessario considerare anche tutte queste colonne:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Risposte correlate:

Un elenco di pro e contro , i più grandi pro (IMO) in grassetto:

Viste dello schema di informazioni

  • spesso più semplice (dipende)
  • lento
  • preelaborato, che può o meno soddisfare le tue esigenze
  • selettivo (gli utenti vedono solo gli oggetti per i quali dispongono dei privilegi)
  • conforme a uno standard SQL (implementato da alcuni dei principali RDBMS)
  • per lo più portatile nelle principali versioni di Postgres
  • non richiedono conoscenze specifiche su Postgres
  • gli identificatori sono descrittivi, lunghi e talvolta imbarazzanti

Cataloghi di sistema

  • spesso più complesso (dipende), più vicino alla fonte
  • veloce
  • completo (colonne di sistema come oidincluse)
  • non conforme a uno standard SQL
  • meno portatile tra le principali versioni di Postgres (ma le basi non cambieranno)
  • richiede conoscenze più specifiche su Postgres
  • gli identificatori sono concisi, meno descrittivi ma convenientemente brevi

Quesito arbitrario

Per ottenere lo stesso elenco di nomi e tipi di colonne da una query, è possibile utilizzare un semplice trucco: CREARE una tabella temporanea dall'output della query, quindi utilizzare le stesse tecniche di cui sopra.

È possibile aggiungere LIMIT 0, poiché non sono necessari dati effettivi:

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

Per ottenere il tipo di dati di singole colonne, puoi anche utilizzare la funzione pg_typeof():

SELECT pg_typeof(1);

Grazie mille. Ho cercato per un po 'come ottenere il tipo di dati della colonna in pg_attribute e ho appena trovato questo post. Apprezzo il tuo post.
Melinda,

Ciò è utile in generale, ma non risponde alla domanda originale su come ottenere informazioni sui tipi di dati delle colonne fornite da un'istruzione SELECT. E 'stato , non sulle colonne di viste o tabelle, che ovviamente risiedono nei cataloghi di sistema e vengono mostrati nello schema informazioni pure.
Holger Jakobs,


2

Se hai accesso a pg_catalog e usi PgAdmin3, consiglio vivamente una soluzione che ho trovato sul blog di Valentine's Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get-table-fields. html ). È una macro PgAdmin3 a cui è possibile accedere con un collegamento per visualizzare la definizione del nome di una tabella selezionata.

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;

Funziona come un fascino ed estremamente utile.


1

Usa le information_schemaviste , sono standard SQL e contengono le informazioni che desideri.

È inoltre possibile accedere direttamente pg_class, pg_attributeecc, ma questo è portabile e spesso fiddlier; potrebbe essere necessario funzioni di aiuto comeoidvectortypes , pg_get_function_arguments, ecc per alcune cose.

Se vuoi vedere come psqlesegue qualcosa del genere \dt, esegui psql -E: stamperà la query. Tuttavia, di solito è meglio usare il information_schemase soddisferà le tue esigenze.


1

Questo può essere eccessivamente semplice, ma pgAdmin4 mostra i tipi di campo nei risultati di output. Le altre soluzioni sopra sono probabilmente più eleganti, ma quando ho solo bisogno di una risposta rapida, trovo che la GUI per le query di pgAdmin4 funzioni abbastanza bene. Cercare di capire il tipo di campo di un campo calcolato restituito da una vista o una funzione può essere complicato.

inserisci qui la descrizione dell'immagine


È molto bello che pgAdmin4 faccia questo, ma come ci riesce? Possiamo scoprirlo senza scansionare tutto il codice sorgente di PgAdmin4?
Holger Jakobs,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.