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 DATABASEkan 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:
\gexecVerzendt 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:
commandmoet 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-coptie.
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.