Cela dépend de ce que vous voulez tester exactement .
Schéma d'information?
Pour trouver "si la table existe" ( peu importe qui le demande ), interroger le schéma d'information ( information_schema.tables
) est incorrect , à proprement parler, car ( par documentation ):
Seules les tables et vues auxquelles l'utilisateur actuel a accès sont affichées (en étant le propriétaire ou en ayant certains privilèges).
La requête fournie par @kong peut renvoyer FALSE
, mais la table peut toujours exister. Il répond à la question:
Comment vérifier si une table (ou une vue) existe et que l'utilisateur actuel y a accès?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Le schéma d'information est principalement utile pour rester portable dans les versions principales et dans différents SGBDR. Mais l'implémentation est lente, car Postgres doit utiliser des vues sophistiquées pour se conformer à la norme ( information_schema.tables
c'est un exemple assez simple). Et certaines informations (comme les OID) sont perdues lors de la traduction à partir des catalogues système - qui contiennent en fait toutes les informations.
Catalogues système
Votre question était:
Comment vérifier si une table existe?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
AND c.relkind = 'r' -- only tables
);
Utilisez les catalogues système pg_class
et pg_namespace
directement, ce qui est également beaucoup plus rapide. Cependant, par documentation surpg_class
:
Le catalogue pg_class
répertorie les tables et presque tout le reste qui a des colonnes ou qui est autrement similaire à une table. Cela inclut les index (mais voir aussi pg_index
), les séquences , les vues , les vues matérialisées , les types composites et les tables TOAST ;
Pour cette question particulière, vous pouvez également utiliser la vue systèmepg_tables
. Un peu plus simple et plus portable dans les principales versions de Postgres (ce qui n'est guère préoccupant pour cette requête de base):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Les identifiants doivent être uniques parmi tous les objets mentionnés ci-dessus. Si vous souhaitez demander:
Comment vérifier si un nom pour une table ou un objet similaire dans un schéma donné est pris?
SELECT EXISTS (
SELECT FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'schema_name'
AND c.relname = 'table_name'
);
Alternative: cast vers regclass
SELECT 'schema_name.table_name'::regclass
Cela déclenche une exception si la table (éventuellement qualifiée par le schéma) (ou tout autre objet occupant ce nom) n'existe pas.
Si vous ne qualifiez pas de schéma le nom de la table, une conversion par regclass
défaut en search_path
et renvoie l'OID de la première table trouvée - ou une exception si la table ne figure dans aucun des schémas répertoriés. Notez que les schémas système pg_catalog
et pg_temp
(le schéma pour les objets temporaires de la session en cours) font automatiquement partie du search_path
.
Vous pouvez l'utiliser et intercepter une exception possible dans une fonction. Exemple:
Une requête comme ci-dessus évite d'éventuelles exceptions et est donc légèrement plus rapide.
Beaucoup plus simple maintenant:
SELECT to_regclass('schema_name.table_name');
Identique au casting, mais ça revient ...
... null plutôt que de lancer une erreur si le nom n'est pas trouvé
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]
pg_tables
est en fait une bonne idée pour "Comment vérifier si une table existe?" (Vérification des tables seulement ., Et non à d' autres fins, comme expliqué ci - dessus également,pg_tables
est une vue impliquant plusieurs tables (pg_class
,pg_namespace
,pg_tablespace
), ce qui est un peu plus cher La raison la plus importante. Je suis habitué à la requêtepg_class
directement et n'a pas pensezpg_tables
à en écrivant cette réponse. Je l'ai ajouté ci-dessus maintenant, merci.pg_my_temp_schema()
pour obtenir l'OID du schéma temporaire réel s'il existe. (Mais les vues dans leinformation_schema
n'incluent pas d'OID. Vous pourriezSELECT nspname FROM pg_namespace WHERE OID = pg_my_temp_schema()
) Votre test a plusieurs faiblesses. Un test correct seraittable_schema LIKE 'pg\_temp\_%'
ou plus stricte:table_schema ~ '^pg_temp_\d+$'
.Utilisez peut-être information_schema :
la source
Pour PostgreSQL 9.3 ou moins ... Ou qui aime tout normalisé au texte
Trois saveurs de mon ancienne bibliothèque SwissKnife:
relname_exists(anyThing)
,relname_normalized(anyThing)
etrelnamechecked_to_array(anyThing)
. Tous les contrôles de la table pg_catalog.pg_class , et retourne les types de données universels standard ( booléen , texte ou texte []).la source