web-dev-qa-db-fra.com

Requête pour renvoyer les noms des colonnes de sortie et les types de données d'une requête, d'une table ou d'une vue

Existe-t-il une requête ou une commande PostgreSQL qui renvoie les noms de champs et les types de champs d'une requête, d'une table ou d'une vue?

Par exemple, une solution si elle est appliquée à une requête SELECT simple comme SELECT * from person devrait renvoyer une liste comme:

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

J'ai recherché le information_schema vues décrites dans une réponse ci-dessous et qui semblent très bien couvrir les tableaux, et je soupçonne que cela couvre également les vues mais je n'ai pas encore vérifié cela.

La dernière est toute requête SELECT arbitraire mais valide, par exemple impliquant, JOINS, UNIONS etc, sur la base de données. Existe-t-il une procédure intégrée ou une autre procédure stockée ou un script qui peut renvoyer la même chose pour toute QUERY valide?

Je développe un programme qui crée des données et des formulaires de requête et les informations sont nécessaires pour la validation des données et l'exécution de fonctions sur les données retournées.

22
vfclists

Schéma d'information vs catalogues système

Nous avons eu des discussions à ce sujet à plusieurs reprises. Le schéma d'information sert à certaines fins. Si vous connaissez votre chemin dans les catalogues système, ceux-ci servent la plupart des objectifs mieux, IMO. Les catalogues système sont la véritable source de toutes les informations.

Le schéma d'information fournit des vues standardisées qui facilitent la portabilité, principalement sur les principales versions de Postgres, car la portabilité sur différentes plates-formes SGBDR est généralement une illusion une fois que vos requêtes sont sophistiquées. assez pour avoir besoin de rechercher des catalogues système. Et, notamment, Oracle ne prend toujours pas en charge le schéma d'information.

Les vues dans le schéma d'informations doivent parcourir plusieurs cercles pour obtenir un format conforme à la norme. Cela les rend lents, parfois très lents. Comparez les plans et les performances de ces objets de base:

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

La différence est remarquable. Cela dépend vraiment de ce que vous recherchez.

Votre exemple

Pour votre exemple SELECT * from tbl, Comparez les deux requêtes ci-dessous pour ce tableau simple:

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

En utilisant 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() renvoie le type complet avec tous les modificateurs:

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

Notez également que le transtypage en regclass résout le nom de la table de façon quelque peu intelligente en fonction du search_path Actuel. Il déclenche également une exception si le nom n'est pas valide. Détails:

En utilisant information_schema.columns:

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

Les informations sont standardisées, mais incomplètes:

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

Pour obtenir des informations complètes sur le type de données, vous devez également prendre en compte toutes ces colonnes:

character_maximum_length
character_octet_length
numeric_precision
numeric_precision_radix
numeric_scale
datetime_precision
interval_type
interval_precision

Réponses associées:

Une liste des avantages et inconvénients , les plus grands avantages (IMO) en gras:

Vues du schéma d'information

  • souvent plus simple (dépend)
  • lent
  • prétraité, qui peut ou non répondre à vos besoins
  • sélectif (les utilisateurs ne voient que les objets pour lesquels ils ont des privilèges)
  • conforme à une norme SQL (qui est implémentée par certains des principaux SGBDR)
  • principalement portable sur les principales versions de Postgres
  • ne nécessitent pas beaucoup de connaissances spécifiques sur Postgres
  • les identifiants sont descriptifs, longs et parfois maladroits

Catalogues système

  • souvent plus complexe (dépend), plus proche de la source
  • rapide
  • complete (colonnes système comme oid incluses)
  • ne se conforme pas à une norme SQL
  • moins portable sur les principales versions de Postgres (mais les bases ne vont pas changer)
  • nécessitent des connaissances plus spécifiques sur Postgres
  • les identifiants sont concis, moins descriptifs mais commodément courts

Requête arbitraire

Pour obtenir la même liste de noms et types de colonnes à partir d'une requête, vous pouvez utiliser une astuce simple: CRÉER une table temporaire à partir de la sortie de la requête, puis utiliser les mêmes techniques que ci-dessus.

Vous pouvez ajouter LIMIT 0, Car vous n'avez pas besoin de données réelles:

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

Pour obtenir le type de données de colonnes individuelles, vous pouvez également utiliser la fonction pg_typeof() :

SELECT pg_typeof(1);
25
Erwin Brandstetter

Vous pouvez utiliser le client de ligne de commande psql.

\dt affichera une liste de tableaux

\dv affichera une liste de vues

\d [object_name] décrira le schéma de la table ou de la vue

Je ne sais pas comment vous décririez une requête.

Plus d'informations: https://manikandanmv.wordpress.com/tag/basic-psql-commands/

2
Neil McGuigan

Si vous avez accès au pg_catalog et utilisez PgAdmin3, je recommande fortement une solution que j'ai trouvée sur le blog de Valentine's Tech ( http://tech.valgog.com/2011/02/pgadmin-iii-macros-get- table-fields.html ). Il s'agit d'une macro PgAdmin3 accessible avec un raccourci pour afficher la définition d'un nom de table sélectionné.

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;

Fonctionne comme un charme et extrêmement utile.

2
marcopolo

Utilisez le information_schema vues , elles sont standard SQL et contiennent les informations que vous souhaitez.

Vous pouvez également accéder directement à pg_class, pg_attribute, etc., mais ce n'est pas transférable et souvent plus compliqué; vous pouvez avoir besoin de fonctions d'assistance comme oidvectortypes , pg_get_function_arguments, etc. pour certaines choses.

Si vous voulez voir comment psql exécute quelque chose comme \dt, courir psql -E - il imprimera la requête. Cependant, il est généralement préférable d'utiliser le information_schema si cela répond à vos besoins.

1
Craig Ringer

Cela peut être trop simple, mais pgAdmin4 affiche les types de champs dans les résultats de sortie. Les autres solutions ci-dessus sont probablement plus élégantes, mais quand j'ai juste besoin d'une réponse rapide, je trouve que l'interface graphique de requête de pgAdmin4 fonctionne assez bien. Essayer de comprendre le type de champ d'un champ calculé renvoyé par une vue ou une fonction peut être délicat.

enter image description here

1
David A