존재하지 않는 경우 PostgreSQL 테이블 생성


175

MySQL 스크립트에서 다음을 작성할 수 있습니다.

CREATE TABLE IF NOT EXISTS foo ...;

... 다른 것들 ...

그런 다음 테이블을 다시 만들지 않고도 스크립트를 여러 번 실행할 수 있습니다.

PostgreSQL에서 어떻게합니까?

답변:


279

이 기능은 Postgres 9.1 에서 구현되었습니다 .

CREATE TABLE IF NOT EXISTS myschema.mytable (i integer);



들어 이전 버전 , 여기를 해결하려면 함수는 다음과 같습니다

CREATE OR REPLACE FUNCTION create_mytable ()
  RETURNS void AS
$func$
BEGIN
   IF EXISTS (SELECT FROM pg_catalog.pg_tables 
              WHERE  schemaname = 'myschema'
              AND    tablename  = 'mytable') THEN
      RAISE NOTICE 'Table myschema.mytable already exists.';
   ELSE
      CREATE TABLE myschema.mytable (i integer);
   END IF;
END
$func$ LANGUAGE plpgsql;

요구:

SELECT create_mytable();        -- call as many times as you want. 

노트:

  • schemanametablename인은 pg_tables대소 문자를 구분합니다. CREATE TABLE명령문 에서 식별자를 큰 따옴표로 묶는 경우 정확히 동일한 철자를 사용해야합니다. 그렇지 않으면 소문자 문자열을 사용해야합니다. 보다:

  • pg_tables실제 테이블 만 포함 합니다. 식별자는 여전히 관련 객체에 의해 점유 될 수 있습니다. 보다:

  • 역할 경우 실행 이 기능이 테이블을 작성하는 데 필요한 권한이없는 사용자가 사용할 수있는 SECURITY DEFINER기능과 그것을 만들 소유 필요한 권한을 가진 다른 역할. 이 버전은 충분히 안전합니다.


기존 postgres 8.4 데이터베이스를 사용해야합니다. 이 핵은 트릭을 수행합니다, 감사합니다!
무한의

1
@Boundless : 편집 내용이 "너무 작음"으로 거부 된 것으로 확인되었습니다. 아프지 않기 때문에 적용했습니다. 그러나 CREATE FUNCTION한 번만 실행해야합니다 . 그건 SELECT create_mytable();당신이 여러 번 호출 할 수 있음.
Erwin Brandstetter 3:30에

1
Brandstetter : 동의합니다. 내가 겪었던 문제는 함수가 생성되었는지 여부를 알지 못한다는 것입니다 (테이블이 있거나 존재하지 않는 것처럼). 그래서 함수를 호출하기 전에 함수가 생성되었는지 확인하고 싶습니다.
경계없는

83

이 시도:

CREATE TABLE IF NOT EXISTS app_user (
  username varchar(45) NOT NULL,
  password varchar(450) NOT NULL,
  enabled integer NOT NULL DEFAULT '1',
  PRIMARY KEY (username)
)

이것은 실제로 더 깨끗한 솔루션입니다. 공감해야합니다.
SDReyes

4
사실, 나는 '기능'과 관련된 솔루션이 얼마나 많은지 두려워합니다.
SDReyes

8
@SDReyes 다른 솔루션은 Postgres 9.1 이전에 게시되었으며 IF NOT EXISTS옵션 이 포함되었습니다 .
Kris

2
이 답변이 @ erwin-brandstetter 답변 자체가 어떻게 완성되었는지에 대해서는 확실하지 않습니다.
comiventor

@comiventor가 정확합니다. 이것은 매개 변수 사용법이 어떻게 표시되는지를 보여줍니다. 이것은 조금 도움이됩니다.
Angry 84

8

모든 테이블에 재사용 할 수있는 기존 답변에서 일반적인 솔루션을 만들었습니다.

CREATE OR REPLACE FUNCTION create_if_not_exists (table_name text, create_stmt text)
RETURNS text AS
$_$
BEGIN

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_tables 
    WHERE    tablename  = table_name
    ) THEN
   RETURN 'TABLE ' || '''' || table_name || '''' || ' ALREADY EXISTS';
ELSE
   EXECUTE create_stmt;
   RETURN 'CREATED';
END IF;

END;
$_$ LANGUAGE plpgsql;

용법:

select create_if_not_exists('my_table', 'CREATE TABLE my_table (id integer NOT NULL);');

쿼리 매개 변수에서 테이블 이름을 추출하는 경우 하나의 매개 변수 만 사용하면 더 간단해질 수 있습니다. 또한 스키마를 생략했습니다.


3

이 솔루션은 Erwin Brandstetter의 답변과 다소 유사하지만 SQL 언어 만 사용합니다.

모든 PostgreSQL 설치에 기본적으로 plpqsql 언어가있는 것은 아닙니다. 즉 CREATE LANGUAGE plpgsql, 함수를 작성하기 전에 호출 한 후 언어를 다시 제거하여 데이터베이스를 이전과 동일한 상태로 두어야합니다 (데이터베이스의 경우에만 해당) plpgsql 언어가 없었습니다). 복잡성이 어떻게 증가하는지보십시오?

스크립트를 로컬로 실행하는 경우 plpgsql을 추가해도 문제가되지 않을 수 있습니다. 그러나 스크립트를 고객에서 스키마를 설정하는 데 사용하는 경우 고객 데이터베이스에 이와 같은 변경 사항을 남기지 않는 것이 좋습니다.

이 솔루션은 Andreas Scherbaum의 게시물에서 영감을 받았습니다 .

-- Function which creates table
CREATE OR REPLACE FUNCTION create_table () RETURNS TEXT AS $$
    CREATE TABLE table_name (
       i int
    );
    SELECT 'extended_recycle_bin created'::TEXT;
    $$
LANGUAGE 'sql';

-- Test if table exists, and if not create it
SELECT CASE WHEN (SELECT true::BOOLEAN
    FROM   pg_catalog.pg_tables 
    WHERE  schemaname = 'public'
    AND    tablename  = 'table_name'
  ) THEN (SELECT 'success'::TEXT)
  ELSE (SELECT create_table())
END;

-- Drop function
DROP FUNCTION create_table();

plpgsql을 사용할 수있는 경우에도 솔루션은 훌륭합니다. 특정 시점에 존재하지 않는 객체에 대한 뷰 및 기능을 쉽게 생성 할 수 있습니다. 외부 서버의 테이블에 대한보기 당신은 내 하루를 구했다! 감사!
Alex Yu

3

존재하지 않으면 CREATE TABLE이 없습니다 ...하지만 간단한 절차를 작성할 수 있습니다.

CREATE OR REPLACE FUNCTION prc_create_sch_foo_table() RETURNS VOID AS $$
BEGIN

EXECUTE 'CREATE TABLE /* IF NOT EXISTS add for PostgreSQL 9.1+ */ sch.foo (
                    id serial NOT NULL, 
                    demo_column varchar NOT NULL, 
                    demo_column2 varchar NOT NULL,
                    CONSTRAINT pk_sch_foo PRIMARY KEY (id));
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column ON sch.foo(demo_column);
                   CREATE INDEX /* IF NOT EXISTS add for PostgreSQL 9.5+ */ idx_sch_foo_demo_column2 ON sch.foo(demo_column2);'
               WHERE NOT EXISTS(SELECT * FROM information_schema.tables 
                        WHERE table_schema = 'sch' 
                            AND table_name = 'foo');

         EXCEPTION WHEN null_value_not_allowed THEN
           WHEN duplicate_table THEN
           WHEN others THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM;

END; $$ LANGUAGE plpgsql;

3

존재하지 않으면 CREATE TABLE이 없습니다 ...하지만 간단한 절차를 작성할 수 있습니다.

CREATE OR REPLACE FUNCTION execute(TEXT) RETURNS VOID AS $$
BEGIN
  EXECUTE $1;
END; $$ LANGUAGE plpgsql;


SELECT 
  execute($$
      CREATE TABLE sch.foo 
      (
        i integer
      )
  $$) 
WHERE 
  NOT exists 
  (
    SELECT * 
    FROM information_schema.tables 
    WHERE table_name = 'foo'
      AND table_schema = 'sch'
  );

트리거는 항상 작동하지 않습니다 내부 : gist.github.com/igilfanov/4df5e90d8a88d653132746a223639f45 오류 : 관계 "푸"이미 존재
igilfanov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.