sql >> Database >  >> RDS >> PostgreSQL

Simuleren CREATE DATABASE ALS NIET BESTAAT voor PostgreSQL?

Beperkingen

U kunt de systeemcatalogus pg_database . vragen - toegankelijk vanuit elke database in hetzelfde databasecluster. Het lastige is dat CREATE DATABASE kan alleen als een enkele instructie worden uitgevoerd. De handleiding:

CREATE DATABASE kan niet worden uitgevoerd binnen een transactieblok.

Het kan dus niet rechtstreeks binnen een functie worden uitgevoerd of DO statement, waar het impliciet in een transactieblok zou staan. SQL-procedures, geïntroduceerd met Postgres 11, kunnen hier ook niet bij helpen.

Oplossing vanuit psql

U kunt er vanuit psql omheen werken door de DDL-instructie voorwaardelijk uit te voeren:

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

De handleiding:

\gexec

Verzendt de huidige querybuffer naar de server en behandelt vervolgens elke kolom van elke rij van de uitvoer van de query (indien aanwezig) als een uit te voeren SQL-instructie.

Tussenoplossing vanuit de shell

Met \gexec je hoeft psql maar één keer te bellen :

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

Mogelijk hebt u meer psql-opties nodig voor uw verbinding; rol, poort, wachtwoord, ... Zie:

  • Voer batchbestand uit met psql-opdracht zonder wachtwoord

Hetzelfde kan niet worden aangeroepen met psql -c "SELECT ...\gexec" sinds \gexec is een psql-meta‑opdracht en de -c optie verwacht een enkele opdracht waarvoor in de handleiding staat:

command moet ofwel een opdrachtreeks zijn die volledig door de server kan worden geparseerd (d.w.z. het bevat geen psql-specifieke functies), of een enkele backslash-opdracht. U kunt dus geen SQL- en psql-meta-commando's combineren binnen een -c optie.

Tussenoplossing vanuit Postgres-transactie

Je zou een dblink . kunnen gebruiken verbinding terug naar de huidige database, die buiten het transactieblok draait. Effecten kunnen daarom ook niet worden teruggedraaid.

Installeer hiervoor de extra module dblink (eenmaal per database):

  • Hoe dblink gebruiken (installeren) in PostgreSQL?

Dan:

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

Nogmaals, je hebt mogelijk meer psql-opties nodig voor de verbinding. Zie het toegevoegde antwoord van Ortwin:

  • DATABASE MAKEN ALS DAT NIET BESTAAT, simuleren voor PostgreSQL?

Gedetailleerde uitleg voor dblink:

  • Hoe voer ik grote niet-blokkerende updates uit in PostgreSQL?

U kunt hier een functie van maken voor herhaald gebruik.



  1. Kunnen we Oracle tools.jar opnieuw distribueren?

  2. Reguliere expressies binnen SQL Server

  3. Waarom een ​​JOIN-clausule gebruiken versus een WHERE-voorwaarde?

  4. Hernoemen van inplugbare database