sql >> Databasteknik >  >> RDS >> PostgreSQL

Simulera SKAPA DATABAS OM INTE FINNS för PostgreSQL?

Begränsningar

Du kan fråga systemkatalogen pg_database - tillgänglig från vilken databas som helst i samma databaskluster. Det knepiga är att CREATE DATABASE kan endast köras som en enskild sats. Manualen:

CREATE DATABASE kan inte köras i ett transaktionsblock.

Så det kan inte köras direkt i en funktion eller DO uttalande, där det skulle vara inuti ett transaktionsblock implicit. SQL-procedurer, introducerade med Postgres 11, kan inte heller hjälpa till med detta.

Lösning inifrån psql

Du kan kringgå det inifrån psql genom att köra DDL-satsen villkorligt:

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

Manualen:

\gexec

Skickar den aktuella frågebufferten till servern och behandlar sedan varje kolumn i varje rad av frågans utdata (om någon) som en SQL-sats som ska köras.

Lösning från skalet

Med \gexec du behöver bara anropa psql en gång :

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

Du kan behöva fler psql-alternativ för din anslutning; roll, port, lösenord, ... Se:

  • Kör batchfil med kommandot psql utan lösenord

Detsamma kan inte anropas med psql -c "SELECT ...\gexec" sedan \gexec är ett psql-metakommando och -c alternativet förväntar sig ett enda kommando för vilken manualen säger:

command måste antingen vara en kommandosträng som är helt tolkbar av servern (dvs. den innehåller inga psql-specifika funktioner) eller ett enstaka omvänt snedstreck-kommando. Du kan alltså inte blanda SQL- och psql-metakommandon inom en -c alternativ.

Lösning inifrån Postgres-transaktionen

Du kan använda en dblink anslutning tillbaka till den aktuella databasen, som körs utanför transaktionsblocket. Effekter kan därför inte heller rullas tillbaka.

Installera tilläggsmodulen dblink för detta (en gång per databas):

  • Hur man använder (installerar) dblink i PostgreSQL?

Sedan:

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$;

Återigen kan du behöva fler psql-alternativ för anslutningen. Se Ortwins tillagda svar:

  • Simulera SKAPA DATABAS OM INTE FINNS för PostgreSQL?

Detaljerad förklaring för dblink:

  • Hur gör jag stora icke-blockerande uppdateringar i PostgreSQL?

Du kan göra detta till en funktion för upprepad användning.



  1. Neo4j - Släpp en begränsning med Cypher

  2. Prestandavärde för COMB-guider

  3. Hur får jag information om en index- och tabellägare i Oracle?

  4. Välj Bulk Collect into Oracle Exempel