2013-08-22 26 views
50

Chcę utworzyć bazę danych, która nie istnieje w JDBC. W przeciwieństwie do MySQL, PostgreSQL nie obsługuje składni create if not exists. Jaki jest najlepszy sposób na osiągnięcie tego?Symulować tworzenie bazy danych, jeśli nie istnieje dla PostgreSQL?

Aplikacja nie wie, czy istnieje baza danych, czy nie. Powinno to sprawdzić i jeśli istnieje baza danych, powinna zostać użyta. Dlatego połączenie z żądaną bazą danych ma sens, a jeśli połączenie nie powiedzie się z powodu braku bazy danych, należy utworzyć nową bazę danych (poprzez połączenie z domyślną bazą danych postgres). Sprawdziłem kod błędu zwrócony przez PostgreSQL, ale nie mogłem znaleźć żadnego odpowiedniego kodu tego samego gatunku.

Inną metodą osiągnięcia tego byłoby połączenie się z bazą danych postgres i sprawdzenie, czy istnieje pożądana baza danych i podjęcie odpowiednich działań. Drugi jest nieco żmudny do opracowania.

Czy istnieje sposób na uzyskanie tej funkcji w Postgresie?

Odpowiedz

43

Możesz poprosić o katalog systemowy. Najtrudniejszą częścią jest (jak komentowano), że można wykonać tylko jedną instrukcję. Per documentation:

CREATE DATABASE cannot be executed inside a transaction block.

Więc nie można uruchomić wewnątrz funkcji lub DO oświadczenie, w którym byłoby wewnątrz bloku transakcji w sposób dorozumiany. Można to obejść, używając połączenia dblink z powrotem do bieżącej bazy danych, która działa poza blokiem transakcji. Efekty nie mogą również zostać wycofane.

trzeba zainstalować dodatkowy moduł dblink (raz na db):

wówczas:

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, w jaki sposób to działa:

Testowany z Postgres 9.3. Możesz to uczynić funkcją wielokrotnego użytku.

+0

Jak możemy to zapisać za pomocą 'jdbc' lub osadzić to w kodzie java. –

+1

@AmanDeepGautam: To jest prosta instrukcja SQL.Powinieneś być w stanie wykonać go jak każdy inny z 'stmt.executeQuery (zapytanie)'. –

+1

Niestety 9.3 (co najmniej) tego nie lubi: "BŁĄD: TWORZENIE BAZY DANYCH nie może być wykonane z ciągu funkcji lub wielu poleceń" –

5

musiałem użyć nieco rozszerzoną wersję @Erwin Brandstetter używany:

DO 
$do$ 
DECLARE 
    _db TEXT := 'some_db'; 
    _user TEXT := 'posrgres'; 
    _password TEXT := 'posrgres'; 
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 plus musiałem dostarczyć poświadczenia dblink. Działa z Postgres 9.4.

64

inna alternatywa, tylko w przypadku, gdy chcesz mieć skrypt, który tworzy bazę danych, jeśli nie istnieje, a inaczej po prostu utrzymuje ją, jak to 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" 

Znalazłem to być pomocne w devops skrypty obsługi administracyjnej, które możesz uruchomić wielokrotnie w tym samym wystąpieniu.

+0

To nie działa dla mnie. 'c: \ Program Files \ PostgreSQL \ 9.6 \ bin $ psql.exe -U admin -tc" WYBIERZ 1 Z pg_database WHERE datname = 'my_db' "| grep -q 1 || psql -U admin -c "CREATE DATABASE my_db" "grep" nie jest rozpoznawany jako polecenie wewnętrzne lub zewnętrzne, program operacyjny lub plik wsadowy. "Co zrobiłem źle? –

+0

Nie masz 'grep' na swojej ścieżce. W systemie Windows 'grep' nie jest instalowany domyślnie. Możesz wyszukać 'gnu grep windows', aby znaleźć wersję, która może działać w systemie Windows. – Rod

+0

Thx @Rod. Po zainstalowaniu grep ten skrypt pracował dla mnie. –