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

Simula CREATE DATABASE SE NON ESISTE per PostgreSQL?

Restrizioni

Puoi chiedere al catalogo di sistema pg_database - accessibile da qualsiasi database nello stesso cluster di database. La parte difficile è che CREATE DATABASE può essere eseguito solo come una singola istruzione. Il manuale:

CREATE DATABASE non può essere eseguito all'interno di un blocco di transazione.

Quindi non può essere eseguito direttamente all'interno di una funzione o DO istruzione, dove sarebbe implicitamente all'interno di un blocco di transazione. Anche le procedure SQL, introdotte con Postgres 11, non possono essere d'aiuto.

Soluzione alternativa da psql

Puoi aggirarlo dall'interno di psql eseguendo l'istruzione DDL in modo condizionale:

SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec

Il manuale:

\gexec

Invia il buffer della query corrente al server, quindi tratta ogni colonna di ogni riga dell'output della query (se presente) come un'istruzione SQL da eseguire.

Soluzione alternativa dalla shell

Con \gexec devi solo chiamare psql una volta :

echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql

Potresti aver bisogno di più opzioni psql per la tua connessione; ruolo, porta, password, ... Vedi:

  • Esegui file batch con il comando psql senza password

Lo stesso non può essere chiamato con psql -c "SELECT ...\gexec" da \gexec è un metacomando psql e il -c l'opzione prevede un singolo comando per cui il manuale riporta:

command deve essere una stringa di comando completamente analizzabile dal server (ovvero, non contiene funzionalità specifiche di psql) o un singolo comando barra rovesciata. Quindi non puoi combinare meta-comandi SQL e psql all'interno di un -c opzione.

Soluzione alternativa dalla transazione Postgres

Potresti usare un dblink connessione al database corrente, che viene eseguito al di fuori del blocco della transazione. Pertanto, anche gli effetti non possono essere annullati.

Installa il modulo aggiuntivo dblink per questo (una volta per database):

  • Come usare (installare) dblink in PostgreSQL?

Quindi:

DO
$do$
BEGIN
   IF EXISTS (SELECT FROM pg_database WHERE datname = 'mydb') THEN
      RAISE NOTICE 'Database already exists';  -- optional
   ELSE
      PERFORM dblink_exec('dbname=' || current_database()  -- current db
                        , 'CREATE DATABASE mydb');
   END IF;
END
$do$;

Ancora una volta, potresti aver bisogno di più opzioni psql per la connessione. Vedi la risposta aggiunta di Ortwin:

  • Simula CREATE DATABASE SE NON ESISTE per PostgreSQL?

Spiegazione dettagliata per dblink:

  • Come faccio a eseguire aggiornamenti non bloccanti di grandi dimensioni in PostgreSQL?

Puoi renderla una funzione per un uso ripetuto.