2013-08-22 3 views
50

Voglio creare un database che non esiste attraverso JDBC. A differenza di MySQL, PostgreSQL non supporta la sintassi create if not exists. Qual è il modo migliore per farlo?Simulare CREATE DATABASE SE NON ESISTE per PostgreSQL?

L'applicazione non sa se il database esiste o meno. Dovrebbe controllare e se il database esiste dovrebbe essere usato. Quindi ha senso connettersi al database desiderato e se la connessione fallisce a causa della non esistenza del database dovrebbe creare un nuovo database (collegandosi al database postgres predefinito). Ho controllato il codice di errore restituito da Postgres ma non sono riuscito a trovare alcun codice rilevante che sia lo stesso.

Un altro metodo per ottenere ciò sarebbe quello di connettersi al database postgres e verificare se il database desiderato esiste e agire di conseguenza. Il secondo è un po 'noioso da allenare.

C'è un modo per ottenere questa funzionalità in Postgres?

risposta

43

È possibile chiedere il catalogo di sistema. La parte difficile è (come è stato commentato) che CREATE DATABASE può essere eseguito solo come una singola istruzione. Per documentation:

CREATE DATABASE cannot be executed inside a transaction block.

Quindi non può essere eseguito all'interno di una funzione o di DO dichiarazione, dove sarebbe all'interno di un blocco di transazione in modo implicito. Ciò può essere aggirato utilizzando una connessione dblink al database corrente, che viene eseguito al di fuori del blocco di transazione. Pertanto, non è possibile eseguire il rollback degli effetti.

È necessario installare il modulo dblink aggiuntivo (una volta al db):

Poi:

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

Una spiegazione dettagliata su come funziona:

Testato con Postgres 9.3. Potresti renderlo una funzione per l'uso ripetuto.

+0

Come possiamo scrivere questo utilizzando 'jdbc' o incorporarlo nel codice java. –

+1

@AmanDeepGautam: è una semplice istruzione SQL.Dovresti essere in grado di eseguirlo come qualsiasi altro con 'stmt.executeQuery (query)'. –

+1

Sfortunatamente 9.3 (almeno) non piace questo: "ERRORE: CREATE DATABASE non può essere eseguito da una funzione o stringa multi-comando" –

5

ho dovuto usare una versione leggermente estesa @Erwin Brandstetter utilizzato:

DO 
$do$ 
DECLARE 
    _db TEXT := 'some_db'; 
    _user TEXT := 'posrgres'; 
    _password TEXT := 'posrgres'; 
BEGIN 
    CREATE EXTENSION IF NOT EXISTS dblink; -- enable extension 
    IF EXISTS (SELECT 1 FROM pg_database WHERE datname = _db) THEN 
    RAISE NOTICE 'Database already exists'; 
    ELSE 
    PERFORM dblink_connect('host=localhost user=' || _user || ' password=' || _password || ' dbname=' || current_database()); 
    PERFORM dblink_exec('CREATE DATABASE ' || _db); 
    END IF; 
END 
$do$ 

ho dovuto abilitare l'estensione dblink, più ho dovuto fornire le credenziali per dblink. Funziona con Postgres 9.4.

64

un'altra alternativa, nel caso in cui si desidera avere uno script di shell che crea il database se non esiste e altrimenti solo mantiene così com'è:

psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U postgres -c "CREATE DATABASE my_db" 

ho trovato questo per essere utile in DevOps script di provisioning, che potresti voler eseguire più volte nella stessa istanza.

+0

Non funziona per me. 'c: \ Programmi \ PostgreSQL \ 9.6 \ bin $ psql.exe -U admin -tc" SELEZIONA 1 DA pg_database WHERE datname = 'my_db' "| grep -q 1 || psql -U admin -c "CREATE DATABASE my_db" "grep" non è riconosciuto come comando interno o esterno, programma eseguibile o file batch. Che cosa ho fatto di sbagliato? –

+0

Non hai 'grep' nel tuo percorso. Su Windows, 'grep' non è installato di default. Puoi cercare 'gnu grep windows' per trovare una versione che possa funzionare su Windows. – Rod

+0

Thx @Rod. Dopo aver installato grep, questo script ha funzionato per me. –