PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

CREATE DATABASE IF NOT EXISTS für PostgreSQL simulieren?

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.