Имитировать создание базы данных, если она не существует для PostgreSQL?
Я хочу создать базу данных, которая не существует через JDBC. В отличие от MySQL, PostgreSQL не поддерживает create if not exists
синтаксис. Как лучше всего этого добиться?
приложение не знает, существует ли база данных или нет. Он должен проверить, и если база данных существует, ее следует использовать. Поэтому имеет смысл подключиться к нужной базе данных, и если соединение не удается из-за отсутствия базы данных, она должна создать новую базу данных (подключившись кpostgres
база данных.) Я проверил код ошибки, возвращенный Postgres, но я не мог найти соответствующий код, который выглядит одинаково.
другим методом для достижения этого было бы подключение к postgres
database и проверьте, существует ли желаемая база данных, и примите соответствующие меры. Во втором немного утомительно работать.
есть ли способ достичь этой функциональности в Postgres?
3 ответов
вы можете спросить системный каталог. Хитрая часть (как было прокомментировано), что CREATE DATABASE
может выполняться только как один оператор. в документации:
CREATE DATABASE
невозможно выполнить внутри блока транзакций.
поэтому его нельзя запустить внутри функции или DO
оператор, где он будет находиться внутри блока транзакций неявно. Это можно обойти, используя dblink
подключение к текущая база данных, которая работает вне блока транзакций. Поэтому эффекты также не могут быть откатаны.
необходимо установить дополнительный модуль dblink (один раз на дБ):
затем:
DO
$do$
BEGIN
IF EXISTS (SELECT 1 FROM pg_database WHERE datname = 'mydb') THEN
RAISE NOTICE 'Database already exists';
ELSE
PERFORM dblink_exec('dbname=' || current_database() -- current db
, 'CREATE DATABASE mydb');
END IF;
END
$do$;
подробное объяснение того, как это работает:
протестировано с Postgres 9.3. Вы можете сделать это функцией для повторного использования.
другая альтернатива, на всякий случай, если вы хотите иметь сценарий оболочки, который создает базу данных, если она не существует, а в противном случае просто сохраняет ее как есть:
psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U postgres -c "CREATE DATABASE my_db"
Я нашел это полезным в сценариях подготовки devops, которые вы можете запустить несколько раз в одном экземпляре.
мне пришлось использовать слегка расширенную версию @Erwin Brandstetter:
DO
$do$
DECLARE
_db TEXT := 'some_db';
_user TEXT := 'postgres_user';
_password TEXT := 'password';
BEGIN
CREATE EXTENSION IF NOT EXISTS dblink; -- enable extension
IF EXISTS (SELECT 1 FROM pg_database WHERE datname = _db) THEN
RAISE NOTICE 'Database already exists';
ELSE
PERFORM dblink_connect('host=localhost user=' || _user || ' password=' || _password || ' dbname=' || current_database());
PERFORM dblink_exec('CREATE DATABASE ' || _db);
END IF;
END
$do$
Я должен был включить dblink
расширение, плюс я должен был предоставить учетные данные для dblink.
Работает с Postgres 9.4.