Einschränkungen
Sie können den Systemkatalog pg_database
fragen - zugänglich von jeder Datenbank im selben Datenbank-Cluster. Der knifflige Teil ist das CREATE DATABASE
kann nur als einzelne Anweisung ausgeführt werden. Das Handbuch:
CREATE DATABASE
kann nicht innerhalb eines Transaktionsblocks ausgeführt werden.
Es kann also nicht direkt innerhalb einer Funktion oder DO
ausgeführt werden -Anweisung, wo sie sich implizit in einem Transaktionsblock befinden würde. SQL-Prozeduren, die mit Postgres 11 eingeführt wurden, können dabei auch nicht helfen.
Problemumgehung innerhalb von psql
Sie können dies innerhalb von psql umgehen, indem Sie die DDL-Anweisung bedingt ausführen:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
Das Handbuch:
\gexec
Sendet den aktuellen Abfragepuffer an den Server und behandelt dann jede Spalte jeder Zeile der Ausgabe der Abfrage (falls vorhanden) als auszuführende SQL-Anweisung.
Workaround von der Shell aus
Mit \gexec
Sie müssen psql nur einmal aufrufen :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
Möglicherweise benötigen Sie weitere psql-Optionen für Ihre Verbindung. Rolle, Port, Passwort, ... Siehe:
- Batchdatei mit psql-Befehl ohne Passwort ausführen
Dasselbe kann nicht mit psql -c "SELECT ...\gexec"
aufgerufen werden seit \gexec
ist ein psql-Meta-Befehl und der -c
Option erwartet einen einzelnen Befehl für die das Handbuch besagt:
command
muss entweder eine Befehlszeichenfolge sein, die vom Server vollständig analysiert werden kann (d. h. sie enthält keine psql-spezifischen Funktionen), oder ein einzelner Backslash-Befehl. Daher können Sie SQL- und psql-Metabefehle nicht innerhalb eines -c
mischen Option.
Workaround innerhalb der Postgres-Transaktion
Sie könnten einen dblink
verwenden Verbindung zurück zur aktuellen Datenbank, die außerhalb des Transaktionsblocks läuft. Effekte können daher auch nicht rückgängig gemacht werden.
Installieren Sie dazu das Zusatzmodul dblink (einmal pro Datenbank):
- Wie wird dblink in PostgreSQL verwendet (installiert)?
Dann:
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$;
Auch hier benötigen Sie möglicherweise weitere psql-Optionen für die Verbindung. Siehe Ortwins hinzugefügte Antwort:
- CREATE DATABASE IF NOT EXISTS für PostgreSQL simulieren?
Ausführliche Erklärung für dblink:
- Wie führe ich große, nicht blockierende Updates in PostgreSQL durch?
Sie können dies zu einer Funktion für wiederholte Verwendung machen.