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

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

CREATE TABLE IF NOT EXISTS foo ...;

… 다른 것들 …

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

PostgreSQL에서 어떻게합니까?



답변

이 기능은 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기능과 그것을 만들 소유 필요한 권한을 가진 다른 역할. 이 버전은 충분히 안전합니다.


답변

이 시도:

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)
)


답변

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

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);');

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


답변

이 솔루션은 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();


답변

존재하지 않으면 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;


답변

존재하지 않으면 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'
  );


답변