복붙노트

[SQL] PostgreSQL을 위해하지 않음있는 경우 DATABASE를 생성 시뮬레이션?

SQL

PostgreSQL을 위해하지 않음있는 경우 DATABASE를 생성 시뮬레이션?

나는 JDBC를 통해 존재하지 않는 데이터베이스를 만들려고합니다. MySQL을 달리 PostgreSQL은하지 구문을 존재하는 경우 생성을 지원하지 않습니다. 이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

데이터베이스가 존재하거나하지 않을 경우 응용 프로그램이 알 수 없습니다. 그것은 확인해야하고 데이터베이스가 존재하는 경우에 사용해야합니다. 이 원하는 데이터베이스와 경우에 연결하는 의미가 그래서 연결이 그것 때문에 (기본 포스트 그레스 데이터베이스에 연결하여) 새 데이터베이스를 작성해야합니다 데이터베이스의 비 존재에 실패합니다. 나는 포스트 그레스에 의해 반환 된 오류 코드를 확인하지만 난 어떤 관련 코드 종 같은 것을 찾을 수 없습니다.

이를 달성하기 위해 또 다른 방법은 포스트 그레스 데이터베이스에 연결하고 원하는 데이터베이스가 존재하는지 확인하고 그에 따라 조치를 취할 것입니다. 두 번째는 운동하는 비트 지루한입니다.

포스트 그레스에서이 기능을 달성 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.동일한 데이터베이스 클러스터의 모든 데이터베이스에서 액세스 할 수 - 당신은 시스템 카탈로그 pg_database을 요청할 수 있습니다. 까다로운 부분은 DATABASE는 하나의 문으로 실행할 수 있습니다 만드는 것이있다. 수동 :

    동일한 데이터베이스 클러스터의 모든 데이터베이스에서 액세스 할 수 - 당신은 시스템 카탈로그 pg_database을 요청할 수 있습니다. 까다로운 부분은 DATABASE는 하나의 문으로 실행할 수 있습니다 만드는 것이있다. 수동 :

    그래서는이 암시 적 트랜잭션 블록 내부 될 함수 또는 DO 문, 내부에서 직접 실행할 수 없습니다.

    (포스트 그레스 (11)에 도입 된 SQL 절차, 하나이하지 도움이 될 수 있습니다.)

    당신은 조건부로 DDL 문을 실행하여 psql 프로그램 내에서 해결할 수 있습니다 :

    SELECT 'CREATE DATABASE mydb'
    WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec
    

    수동 :

    당신은 단지 전화 psql의 필요 \ gexec 회 :

    echo "SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec" | psql
    

    당신은 당신의 연결을위한 더 psql의 옵션을해야 할 수도 있습니다; 역할, 포트, 비밀번호, ... 참조 :

    마찬가지로 호출 할 수 없습니다 psql의 -c "SELECT ... \ gexec"\ gexec하는 psql의 메타 명령과 -c 옵션은 단일 명령 기대 때문에하는 수동 상태에 대한 :

    당신은 외부 트랜잭션 블록의 실행은 현재 데이터베이스에 DBLINK 연결 등을 사용할 수 있습니다. 따라서도 영향을 롤백 할 수 없다.

    이 (한 번 데이터베이스 당)에 대한 추가 모듈 DBLINK를 설치합니다 :

    그때:

    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의 옵션이 필요할 수 있습니다. Ortwin의 추가 답변을 참조하십시오 :

    DBLINK에 대한 상세 설명 :

    당신은 반복 사용하기 위해 이것을 기능을 할 수 있습니다.

  2. ==============================

    2.또 다른 대안은, 단지 경우에 당신은 존재하고 그대로 그렇지 않으면 그냥 유지하지 않는 경우 데이터베이스를 생성 쉘 스크립트를 갖고 싶어 :

    또 다른 대안은, 단지 경우에 당신은 존재하고 그대로 그렇지 않으면 그냥 유지하지 않는 경우 데이터베이스를 생성 쉘 스크립트를 갖고 싶어 :

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

    나는이 같은 인스턴스에 여러 번 실행할 수 있습니다 스크립트를 프로비저닝 개발 운영 팀에 도움이 될 것으로.

  3. ==============================

    3.나는 @Erwin Brandstetter 사용 약간 확장 된 버전을 사용했다 :

    나는 @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에 대한 자격 증명을 제공했다. 포스트 그레스 9.4에서 작동합니다.

  4. ==============================

    4.PostgreSQL는 IF NOT은 CREATE DATABASE 문을 위해 존재 지원하지 않습니다. 단지에서 스키마를 작성 지원됩니다. 또한 데이터베이스가 트랜잭션에 발행 할 수 없습니다 CREATE 따라서 예외 잡기와 DO 블록에있을 수 없습니다.

    PostgreSQL는 IF NOT은 CREATE DATABASE 문을 위해 존재 지원하지 않습니다. 단지에서 스키마를 작성 지원됩니다. 또한 데이터베이스가 트랜잭션에 발행 할 수 없습니다 CREATE 따라서 예외 잡기와 DO 블록에있을 수 없습니다.

    SCHEMA IF가 NOT 발행 존재하고 스키마가 벌써 중복 객체 정보 통지 (안 오류)가 발생합니다 존재 만들 때.

    당신이 데이터베이스 서버에 대한 새 연결을 엽니 다 DBLINK 확장자를 사용하고 거래를 입력하지 않고 쿼리를 실행해야 이러한 문제를 해결합니다. 당신은 빈 문자열을 공급하여 연결 매개 변수를 다시 사용할 수 있습니다.

    아래 NOT은 CREATE SCHEMA IF가 NOT EXISTS처럼 같은 동작으로 존재하는 경우 완벽하게 시뮬레이트 데이터베이스를 만들 PL / pgSQL의 코드입니다. 그것은 errcode를 전파로 통지로 (데이터베이스가 이미 존재하는 경우 발행) DBLINK를 통해 DATABASE, 예외 duplicate_database 캐치 및 변환을 CREATE 호출합니다. 문자열 메시지가 SCHEMA IF가 NOT EXISTS CREATE 않는 방법과 동일한 방법으로 건너 뜁니다 추가했다.

    CREATE EXTENSION IF NOT EXISTS dblink;
    
    DO $$
    BEGIN
    PERFORM dblink_exec('', 'CREATE DATABASE testdb');
    EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
    END
    $$;
    

    이 솔루션은 데이터베이스가 존재 해, 그 자신의 창조물 경우 확인과 데이터베이스가 외부 프로세스 (또는 동일한 스크립트의 다른 인스턴스)을 생성 할 수있는 다른 답변처럼 어떤 경쟁 조건없이.

    또한 데이터베이스를 만들 때 데이터베이스가 이미이 오류가 오류로 전파되고 자동으로 삭제하지 존재 이외의 오류와 함께 실패합니다. duplicate_database 오류 만 캐치가있다. IF NOT 정상적으로 존재하는 그래서 정말 작동합니다.

    직접 또는 거래에서 호출, 자신의 기능에이 코드를 넣을 수 있습니다. 그냥 롤백 (떨어 데이터베이스를 복원 할) 것없는 일.

    (두 번 DO를 통해 다음 직접 호출) 테스트 출력 :

    $ sudo -u postgres psql
    psql (9.6.12)
    Type "help" for help.
    
    postgres=# \set ON_ERROR_STOP on
    postgres=# \set VERBOSITY verbose
    postgres=# 
    postgres=# CREATE EXTENSION IF NOT EXISTS dblink;
    CREATE EXTENSION
    postgres=# DO $$
    postgres$# BEGIN
    postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
    postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
    postgres$# END
    postgres$# $$;
    DO
    postgres=# 
    postgres=# CREATE EXTENSION IF NOT EXISTS dblink;
    NOTICE:  42710: extension "dblink" already exists, skipping
    LOCATION:  CreateExtension, extension.c:1539
    CREATE EXTENSION
    postgres=# DO $$
    postgres$# BEGIN
    postgres$# PERFORM dblink_exec('', 'CREATE DATABASE testdb');
    postgres$# EXCEPTION WHEN duplicate_database THEN RAISE NOTICE '%, skipping', SQLERRM USING ERRCODE = SQLSTATE;
    postgres$# END
    postgres$# $$;
    NOTICE:  42P04: database "testdb" already exists, skipping
    LOCATION:  exec_stmt_raise, pl_exec.c:3165
    DO
    postgres=# 
    postgres=# CREATE DATABASE testdb;
    ERROR:  42P04: database "testdb" already exists
    LOCATION:  createdb, dbcommands.c:467
    
  5. ==============================

    5.당신이 데이터에 대해 상관하지 않는 경우, 먼저 데이터베이스를 삭제 한 다음 다시 만들 수 있습니다 :

    당신이 데이터에 대해 상관하지 않는 경우, 먼저 데이터베이스를 삭제 한 다음 다시 만들 수 있습니다 :

    DROP DATABASE IF EXISTS dbname;
    CREATE DATABASE dbname;
    
  6. ==============================

    6.그냥 CREATEDB CLI 도구를 사용하여 데이터베이스를 만들 :

    그냥 CREATEDB CLI 도구를 사용하여 데이터베이스를 만들 :

    PGHOST="my.database.domain.com"
    PGUSER="postgres"
    PGDB="mydb"
    createdb -h $PGHOST -p $PGPORT -U $PGUSER $PGDB
    

    데이터베이스가 존재하는 경우는 오류를 반환합니다 :

    createdb: database creation failed: ERROR:  database "mydb" already exists
    
  7. ==============================

    7.당신이 쉘을 사용할 수 있다면, 시도

    당신이 쉘을 사용할 수 있다면, 시도

    psql -U postgres -c 'select 1' -d $DB &>dev/null || psql -U postgres -tc 'create database $DB'
    

    내 생각 psql의 -U 포스트 그레스 -c datname = 'my_db'과는 쉬 -c와 결합하기 쉽게 인용 한 유형을 필요로하는 곳에 -d $ DB가 pg_database에서 선택 1보다 쉽습니다 "1 선택".

    내 ansible 작업에서 이것을 사용

    - name: create service database
      shell: docker exec postgres sh -c '{ psql -U postgres -tc "SELECT 1" -d {{service_name}} &> /dev/null && echo -n 1; } || { psql -U postgres -c "CREATE DATABASE {{service_name}}"}'
      register: shell_result
      changed_when: "shell_result.stdout != '1'"
    
  8. ==============================

    8.PostgreSQL을 9.5 이상으로 업그레이드합니다. 경우 (안) 버전 9.5에 도입 된 존재.

    PostgreSQL을 9.5 이상으로 업그레이드합니다. 경우 (안) 버전 9.5에 도입 된 존재.

  9. from https://stackoverflow.com/questions/18389124/simulate-create-database-if-not-exists-for-postgresql by cc-by-sa and MIT license