sql >> Database teknologi >  >> RDS >> PostgreSQL

Simuler OPRET DATABASE, HVIS IKKE FINNES for PostgreSQL?

Begrænsninger

Du kan spørge systemkataloget pg_database - tilgængelig fra enhver database i samme databaseklynge. Den vanskelige del er, at CREATE DATABASE kan kun udføres som en enkelt sætning. Manualen:

CREATE DATABASE kan ikke udføres i en transaktionsblok.

Så det kan ikke køres direkte inde i en funktion eller DO erklæring, hvor det ville være inde i en transaktionsblok implicit. SQL-procedurer, introduceret med Postgres 11, kan heller ikke hjælpe med dette.

Løsning fra psql

Du kan omgå det inde fra psql ved at udføre DDL-sætningen betinget:

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

Manualen:

\gexec

Sender den aktuelle forespørgselsbuffer til serveren og behandler derefter hver kolonne i hver række af forespørgslens output (hvis nogen) som en SQL-sætning, der skal udføres.

Løsning fra skallen

Med \gexec du behøver kun at kalde psql én gang :

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

Du har muligvis brug for flere psql-indstillinger til din forbindelse; rolle, port, adgangskode, ... Se:

  • Kør batchfil med psql-kommando uden adgangskode

Det samme kan ikke kaldes med psql -c "SELECT ...\gexec" siden \gexec er en psql-metakommando og -c option forventer en enkelt kommando for hvilket manualen siger:

command skal enten være en kommandostreng, der er fuldstændig parserbar af serveren (dvs. den indeholder ingen psql-specifikke funktioner), eller en enkelt backslash-kommando. Du kan således ikke blande SQL- og psql-metakommandoer i en -c mulighed.

Løsning fra Postgres-transaktionen

Du kan bruge en dblink forbindelse tilbage til den aktuelle database, som kører uden for transaktionsblokken. Effekter kan derfor heller ikke rulles tilbage.

Installer det ekstra modul dblink til dette (en gang pr. database):

  • Hvordan bruger (installerer) dblink i PostgreSQL?

Så:

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

Igen kan du få brug for flere psql-indstillinger til forbindelsen. Se Ortwins tilføjede svar:

  • Simulerer CREATE DATABASE, HVIS IKKE FINNES for PostgreSQL?

Detaljeret forklaring på dblink:

  • Hvordan laver jeg store ikke-blokerende opdateringer i PostgreSQL?

Du kan gøre denne funktion til gentagen brug.



  1. Arbejde med begivenheder i Oracle Cloud Infrastructure Del 1:grundlæggende service

  2. Sådan beregnes forskellen mellem to tidsstempler i Oracle

  3. Hvordan bruger man en Oracle Ref Cursor fra C# ODP.NET som en ReturnValue Parameter uden at bruge en lagret funktion eller procedure?

  4. Sådan opdateres Identity Column i SQL Server?