Ограничения
Можете да попитате системния каталог pg_database
- достъпен от всяка база данни в същия клъстер от бази данни. Трудната част е CREATE DATABASE
може да се изпълни само като един оператор. Ръководството:
CREATE DATABASE
не може да се изпълни в блок за транзакция.
Така че не може да се изпълнява директно във функция или DO
оператор, където би бил имплицитно вътре в транзакционен блок. SQL процедурите, въведени с Postgres 11, също не могат да помогнат за това.
Заобиколно решение от psql
Можете да го заобиколите от psql, като изпълните оператора DDL условно:
SELECT 'CREATE DATABASE mydb'
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
Ръководството:
\gexec
Изпраща текущия буфер за заявка към сървъра, след което третира всяка колона от всеки ред от изхода на заявката (ако има такава) като SQL оператор, който трябва да бъде изпълнен.
Заобиколно решение от обвивката
С \gexec
трябва само да извикате psql веднъж :
echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
Може да имате нужда от повече psql опции за вашата връзка; роля, порт, парола, ... Вижте:
- Изпълнете пакетен файл с команда psql без парола
Същото не може да бъде извикано с psql -c "SELECT ...\gexec"
тъй като \gexec
е мета-команда psql и -c
опцията очаква една команда за които в ръководството е посочено:
command
трябва да бъде или команден низ, който може да се анализира напълно от сървъра (т.е. не съдържа специфични за psql функции), или единична обратна наклонена черта команда. По този начин не можете да смесвате SQL и psql мета-команди в-c
опция.
Заобиколно решение от транзакцията на Postgres
Можете да използвате dblink
връзка обратно към текущата база данни, която работи извън блока на транзакциите. Следователно ефектите също не могат да бъдат връщани назад.
Инсталирайте допълнителния модул dblink за това (веднъж на база данни):
- Как да използвам (инсталирам) dblink в PostgreSQL?
След това:
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$;
Отново може да се нуждаете от повече psql опции за връзката. Вижте добавения отговор на Ортуин:
- Симулира CREATE DATABASE, АКО НЕ СЪЩЕСТВУВА за PostgreSQL?
Подробно обяснение за dblink:
- Как да направя големи неблокиращи актуализации в PostgreSQL?
Можете да направите това функция за многократна употреба.