Имитировать создание базы данных, если она не существует для 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.