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 mieux la plupart des objectifs , l'OMI. 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 suffisamment sophistiquées pour avoir besoin de rechercher des catalogues système. Et, notamment, Oracle ne prend toujours pas en charge le schéma d'informations.
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 regclass
résout le nom de la table de manière quelque peu intelligente en fonction du courant search_path
. 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 des inconvénients , les plus grands avantages (OMI) en gras:
Vues du schéma d'information
- souvent plus simple (dépend)
- lent
- prétraité, qui peut ou non convenir à 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
- vite
- complète (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);