Dipende da cosa vuoi testare esattamente .
Schema informativo?
Per scoprire "se la tabella esiste" ( indipendentemente da chi lo sta chiedendo ), eseguire una query sullo schema di informazioni ( information_schema.tables
) non è corretto , in senso stretto, perché ( per documentazione ):
Vengono mostrate solo le tabelle e le viste a cui l'utente corrente ha accesso (per mezzo del proprietario o dei privilegi).
La query fornita da @kong può tornare FALSE
, ma la tabella può ancora esistere. Risponde alla domanda:
Come verificare se esiste una tabella (o vista) e l'utente corrente ha accesso ad essa?
SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_schema = 'schema_name'
AND table_name = 'table_name'
);
Lo schema delle informazioni è utile soprattutto per essere trasportabile tra le versioni principali e tra diversi RDBMS. Ma l'implementazione è lenta, perché Postgres deve usare viste sofisticate per conformarsi allo standard ( information_schema.tables
è un esempio piuttosto semplice). E alcune informazioni (come gli OID) si perdono nella traduzione dai cataloghi di sistema, che in realtà contengono tutte le informazioni.
Cataloghi di sistema
La tua domanda era:
Come verificare se esiste una tabella?
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
);
Utilizza i cataloghi di sistema pg_class
e pg_namespace
direttamente, che è anche molto più veloce. Tuttavia, per documentazione supg_class
:
Il catalogo pg_class
cataloga le tabelle e quasi tutto il resto con colonne o è simile a una tabella. Questo include indici (ma vedi anche pg_index
), sequenze , viste , viste materializzate , tipi compositi e tabelle TOAST ;
Per questa domanda particolare puoi anche usare la vista di sistemapg_tables
. Un po 'più semplice e portatile nelle principali versioni di Postgres (il che non preoccupa molto per questa query di base):
SELECT EXISTS (
SELECT FROM pg_tables
WHERE schemaname = 'schema_name'
AND tablename = 'table_name'
);
Gli identificatori devono essere univoci tra tutti gli oggetti sopra menzionati. Se vuoi chiedere:
Come verificare se viene preso un nome per una tabella o un oggetto simile in un determinato schema?
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'
);
Alternativa: cast a regclass
SELECT 'schema_name.table_name'::regclass
Ciò solleva un'eccezione se la tabella (facoltativamente qualificata da schema) (o altro oggetto che occupa quel nome) non esiste.
Se non si qualifica lo schema del nome della tabella, un cast viene regclass
impostato in modo predefinito sull'OID search_path
e restituisce l'OID per la prima tabella trovata, oppure un'eccezione se la tabella non si trova in nessuno degli schemi elencati. Si noti che gli schemi di sistema pg_catalog
e pg_temp
(lo schema per oggetti temporanei della sessione corrente) fanno automaticamente parte di search_path
.
Puoi usarlo e cogliere una possibile eccezione in una funzione. Esempio:
Una query come sopra evita possibili eccezioni ed è quindi leggermente più veloce.
Molto più semplice ora:
SELECT to_regclass('schema_name.table_name');
Come il cast, ma restituisce ...
... null anziché generare un errore se il nome non viene trovato
[[ `psql dbname -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'ejabberd' AND table_name = 'users');"` = 't' ]]