Symulować tworzenie bazy danych, jeśli nie istnieje dla PostgreSQL?

Chcę utworzyć bazę danych, która nie istnieje poprzez JDBC. W przeciwieństwie do MySQL, PostgreSQL nie obsługuje składni create if not exists. Jaki jest najlepszy sposób, aby to osiągnąć?

Aplikacja nie wie, czy baza danych istnieje, czy nie. Powinien sprawdzić i czy baza danych istnieje powinna być użyta. Dlatego warto połączyć się z żądaną bazą danych i jeśli połączenie nie powiedzie się z powodu braku bazy danych, należy utworzyć nową bazę danych (łącząc się z domyślną bazą postgres). I sprawdziłem kod błędu zwrócony przez Postgres, ale nie mogłem znaleźć żadnego odpowiedniego kodu, który byłby taki sam.

Inną metodą, aby to osiągnąć, byłoby połączenie się z bazą danych postgres i sprawdzenie, czy żądana baza danych istnieje i podjęcie odpowiednich działań. Drugi jest trochę nudny do wypracowania.

Czy Jest jakiś sposób na osiągnięcie tej funkcjonalności w Postgres?

Author: Erwin Brandstetter, 2013-08-22

3 answers

Możesz zapytać katalog systemu. Najtrudniejsze jest to, że CREATE DATABASE może być wykonywane tylko jako pojedyncza Instrukcja. wg dokumentacji:

CREATE DATABASE nie można wykonać wewnątrz bloku transakcji.

Więc nie można go uruchomić wewnątrz funkcji lub DO oświadczenie, gdzie znajduje się wewnątrz bloku transakcji bezwarunkowo. Można to jednak obejść, korzystając z połączenia dblink z powrotem do bieżącej bazy danych, która działa poza blok transakcji. Efekty nie mogą być zatem wycofane.

Należy zainstalować dodatkowy moduł dblink (raz na db):

Potem:

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

Szczegółowe wyjaśnienie, jak to działa:

Testowane Z Postgres 9.3. Możesz zrobić z tego funkcję wielokrotnego użytku.

 47
Author: Erwin Brandstetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Inna alternatywa, na wypadek, gdybyś chciał mieć skrypt powłoki, który tworzy bazę danych, jeśli nie istnieje, a w przeciwnym razie zachowuje ją taką, jaka jest:

psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname = 'my_db'" | grep -q 1 || psql -U postgres -c "CREATE DATABASE my_db"

Okazało się, że jest to pomocne w skryptach aprowizacyjnych devops, które można uruchamiać wiele razy na tej samej instancji.

 85
Author: andreasl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 07:47:51

Musiałem użyć nieco rozszerzonej wersji @ Erwin Brandstetter używany:

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$

Musiałem włączyć rozszerzenie dblink, dodatkowo musiałem podać dane uwierzytelniające dla dblink. Współpracuje z Postgres 9.4.

 5
Author: Ortwin Angermeier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-17 16:19:09