Beschränkungen
Sie können den Systemkatalog anfordern, pg_database
auf den von jeder Datenbank im selben Datenbankcluster aus zugegriffen werden kann. Der schwierige Teil ist, dass CREATE DATABASE
nur als einzelne Anweisung ausgeführt werden kann. Das Handbuch:
CREATE DATABASE
kann nicht innerhalb eines Transaktionsblocks ausgeführt werden.
Es kann also nicht direkt in einer Funktion oder DO
Anweisung ausgeführt werden, wo es sich implizit in einem Transaktionsblock befindet.
(SQL-Prozeduren, die mit Postgres 11 eingeführt wurden, können auch hier nicht helfen .)
Problemumgehung innerhalb von psql
Sie können dies in psql umgehen, indem Sie die DDL-Anweisung unter bestimmten Bedingungen 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.
Problemumgehung von der Shell
Mit müssen \gexec
Sie 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:
Dasselbe kann nicht aufgerufen werden, psql -c "SELECT ...\gexec"
da \gexec
es sich um einen psql-Meta-Befehl handelt und die -c
Option einen einzelnen Befehl erwartet, für den im Handbuch Folgendes angegeben ist:
command
muss entweder eine Befehlszeichenfolge sein, die vom Server vollständig analysiert werden kann (dh keine psql-spezifischen Funktionen enthält), oder ein einzelner Backslash-Befehl. Daher können Sie keine SQL- und psql-Metabefehle innerhalb einer -c
Option mischen .
Problemumgehung innerhalb der Postgres-Transaktion
Sie können eine dblink
Verbindung zurück zur aktuellen Datenbank verwenden, die außerhalb des Transaktionsblocks ausgeführt wird. Effekte können daher auch nicht zurückgesetzt werden.
Installieren Sie dazu das zusätzliche Modul dblink (einmal pro Datenbank):
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 mehr psql-Optionen für die Verbindung. Siehe Ortwins hinzugefügte Antwort:
Detaillierte Erklärung für dblink:
Sie können dies zu einer Funktion für die wiederholte Verwendung machen.
dblink_connect
.\gexec
als ich die erste Abfrage von der Shell ausführte, aber es funktionierte.Eine weitere Alternative, nur für den Fall, dass Sie ein Shell-Skript haben möchten, das die Datenbank erstellt, wenn sie nicht vorhanden ist, und sie ansonsten einfach so lässt, wie sie ist:
Ich fand dies hilfreich bei der Bereitstellung von Skripten durch Entwickler, die Sie möglicherweise mehrmals über dieselbe Instanz ausführen möchten.
quelle
c:\Program Files\PostgreSQL\9.6\bin $ psql.exe -U admin -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U admin -c "CREATE DATABASE my_db" 'grep' is not recognized as an internal or external command, operable program or batch file.
Was habe ich falsch gemacht ?grep
auf deinem Weg. Ist unter Windowsgrep
nicht standardmäßig installiert. Sie könnengnu grep windows
nach einer Version suchen, die unter Windows funktioniert.Ich musste eine leicht erweiterte Version verwenden @Erwin Brandstetter verwendet:
Ich musste die
dblink
Erweiterung aktivieren und die Anmeldeinformationen für dblink angeben. Funktioniert mit Postgres 9.4.quelle
Wenn Sie sich nicht für die Daten interessieren, können Sie die Datenbank zuerst löschen und dann neu erstellen:
quelle
PostgreSQL unterstützt nicht
IF NOT EXISTS
fürCREATE DATABASE
Anweisung. Es wird nur in unterstütztCREATE SCHEMA
. Darüber hinausCREATE DATABASE
kann es nicht in einer Transaktion ausgegeben werden, daher kann esDO
mit Ausnahme des Fangens nicht blockiert werden.Wenn
CREATE SCHEMA IF NOT EXISTS
ausgegeben wird und das Schema bereits vorhanden ist, wird ein Hinweis (kein Fehler) mit doppelten Objektinformationen ausgelöst.Um diese Probleme zu lösen, müssen Sie die
dblink
Erweiterung verwenden, die eine neue Verbindung zum Datenbankserver herstellt und die Abfrage ausführt, ohne eine Transaktion abzuschließen. Sie können Verbindungsparameter wiederverwenden, indem Sie eine leere Zeichenfolge angeben.Unten finden Sie
PL/pgSQL
Code, derCREATE DATABASE IF NOT EXISTS
mit demselben Verhalten wie in vollständig simuliertCREATE SCHEMA IF NOT EXISTS
. Es ruftCREATE DATABASE
viadblink
, catch-duplicate_database
Ausnahme auf (die ausgegeben wird, wenn die Datenbank bereits vorhanden ist) und konvertiert sie mit Propagierung in Benachrichtigungerrcode
. Die String-Nachricht wurde, skipping
auf die gleiche Weise angehängt wie sieCREATE SCHEMA IF NOT EXISTS
.Diese Lösung ist ohne Race-Bedingung wie in anderen Antworten, bei denen die Datenbank durch einen externen Prozess (oder eine andere Instanz desselben Skripts) zwischen der Überprüfung, ob eine Datenbank vorhanden ist, und ihrer eigenen Erstellung erstellt werden kann.
Wenn ein
CREATE DATABASE
Fehler mit einem anderen Fehler als der Datenbank bereits vorliegt, wird dieser Fehler als Fehler weitergegeben und nicht stillschweigend verworfen. Es gibt nurduplicate_database
Fehler. Es verhält sich also wirklich so, wie esIF NOT EXISTS
sollte.Sie können diesen Code in eine eigene Funktion einfügen, direkt oder über eine Transaktion aufrufen. Nur ein Rollback (wiederhergestellte Datenbank wiederherstellen) würde nicht funktionieren.
Testausgabe (zweimal über DO und dann direkt aufgerufen):
quelle
Wenn Sie Shell verwenden können, versuchen Sie es
Ich denke, es
psql -U postgres -c "select 1" -d $DB
ist einfacher alsSELECT 1 FROM pg_database WHERE datname = 'my_db'
und braucht nur eine Art von Zitat, mit dem man leichter kombinieren kannsh -c
.Ich benutze dies in meiner ansiblen Aufgabe
quelle
Erstellen Sie einfach die Datenbank mit dem
createdb
CLI-Tool:Wenn die Datenbank vorhanden ist, wird ein Fehler zurückgegeben:
quelle
Upgrade auf PostgreSQL 9.5 oder höher. Wenn (nicht) vorhanden wurde, wurde in Version 9.5 eingeführt.
quelle
if not exists
fürCREATE DATABASE
- nicht einmal in Postgres 11 postgresql.org/docs/current/static/sql-createdatabase.html