PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come verificare se esiste una tabella in un determinato schema

Dipende da cosa vuoi testare esattamente .

Schema di informazioni?

Per trovare "se il tavolo esiste" (non importa chi lo sta chiedendo ), interrogando lo schema delle informazioni (information_schema.tables ) è errato , in senso stretto, perché (per documentazione):

Vengono mostrate solo le tabelle e le viste a cui l'utente corrente ha accesso (in quanto proprietario o privilegio).

La query fornita da @kong può restituire FALSE , ma la tabella può ancora esistere. Risponde alla domanda:

Come verificare se esiste una tabella (o vista) e l'utente corrente vi ha accesso?

SELECT EXISTS (
   SELECT FROM information_schema.tables 
   WHERE  table_schema = 'schema_name'
   AND    table_name   = 'table_name'
   );

Lo schema delle informazioni è utile principalmente per mantenere la portabilità tra le versioni principali e tra diversi RDBMS. Ma l'implementazione è lenta, perché Postgres deve utilizzare viste sofisticate per conformarsi allo standard (information_schema.tables è un esempio piuttosto semplice). E alcune informazioni (come gli OID) vengono perse durante la traduzione dai cataloghi di sistema, il che in realtà trasportare 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
   );

Usa i cataloghi di sistema pg_class e pg_namespace direttamente, che è anche notevolmente più veloce. Tuttavia, secondo la documentazione su pg_class :

Il catalogo pg_class cataloga i tavoli e quasi tutto ciò che ha colonne o è comunque simile a un tavolo. Ciò include indici (ma vedi anche pg_index ), sequenze , viste , viste materializzate , tipi compositi e tabelle TOAST;

Per questa particolare domanda puoi anche usare la vista di sistema pg_tables . Un po' più semplice e più portabile nelle principali versioni di Postgres (che non è certo un problema 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 oggetti di cui sopra. 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'
   );
  • Risposta correlata su dba.SE che discute di "Schema delle informazioni vs. cataloghi di sistema"

Alternativa:trasmettere a regclass

SELECT 'schema_name.table_name'::regclass

Questo solleva un'eccezione se la tabella (facoltativamente qualificata per lo schema) (o altro oggetto che occupa quel nome) non esiste.

Se non qualifichi lo schema del nome della tabella, un cast a regclass il valore predefinito è search_path e restituisce l'OID per la prima tabella trovata o un'eccezione se la tabella non è in nessuno degli schemi elencati. Si noti che gli schemi di sistema pg_catalog e pg_temp (lo schema per gli oggetti temporanei della sessione corrente) fanno automaticamente parte del search_path .

Puoi usarlo e catturare una possibile eccezione in una funzione. Esempio:

  • Verifica se la sequenza esiste in Postgres (plpgsql)

Una query come sopra evita possibili eccezioni ed è quindi leggermente più veloce.

to_regclass(rel_name) in Postgres 9.4+

Molto più semplice ora:

SELECT to_regclass('schema_name.table_name');

Come il cast, ma ritorna...

... null anziché generare un errore se il nome non viene trovato