PostgreSQL создать таблицу, если не существует

В сценарии MySQL вы можете написать:

CREATE TABLE IF NOT EXISTS foo ...;

... другие вещи ...

и затем вы можете запускать сценарий много раз без повторного создания таблицы.

Как вы делаете это в PostgreSQL?

112 голосов | спросил peter2108 19 42009vEurope/Moscow11bEurope/MoscowThu, 19 Nov 2009 22:48:41 +0300 2009, 22:48:41

6 ответов


0

Эта функция была реализована в 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 1 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. 

Примечания:

  • Столбцы schemaname и tablename в pg_tables чувствительны к регистру. Если вы в кавычках идентифицируете идентификаторы в выражении CREATE TABLE, вам нужно использовать точно такое же написание. Если вы этого не сделаете, вам нужно использовать строчные буквы. См:

  • pg_tables содержит только фактические таблицы . Идентификатор все еще может быть занят связанными объектами. См:

  • Если роль выполняет , эта функция не имеет необходимых прав для создания таблицы, которую вы можете использовать SECURITY DEFINER для функции и сделайте ее принадлежит другой роли с необходимыми привилегиями. Эта версия достаточно безопасна.

ответил Erwin Brandstetter 16 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 16 Sep 2011 02:34:25 +0400 2011, 02:34:25
0

Попробуйте это:

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 (user_id)  
)
ответил Achilles Ram Nakirekanti 20 FebruaryEurope/MoscowbSat, 20 Feb 2016 20:28:38 +0300000000pmSat, 20 Feb 2016 20:28:38 +030016 2016, 20:28:38
0

Я создал общее решение из существующих ответов, которое можно использовать для любой таблицы:

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

В дальнейшем можно было бы упростить использование только одного параметра, если бы вы извлекли имя таблицы из параметра запроса. Также я не учел схемы. Не стесняйтесь расширять мое решение, если вы знаете, как это сделать - я еще не настолько глубоко увлечен plpgsql (это первый раз, когда я имею дело с этим).

ответил ifischer 8 +04002013-10-08T17:37:00+04:00312013bEurope/MoscowTue, 08 Oct 2013 17:37:00 +0400 2013, 17:37:00
0

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;
ответил igilfanov 18 AM000000110000000231 2017, 11:16:02
0

Это решение несколько похоже на ответ Эрвина Брандштеттера, но использует только язык SQL.

Не во всех установках PostgreSQL по умолчанию используется язык plpqsql, это означает, что вам может потребоваться вызвать CREATE LANGUAGE plpgsql перед созданием функции и после нее. необходимо снова удалить язык, чтобы оставить базу данных в том же состоянии, в котором она была раньше (но только если в базе данных не было языка plpgsql для начала). Посмотрите, как растет сложность?

Добавление plpgsql может не вызывать проблем при локальном запуске сценария, однако, если сценарий используется для настройки схемы у клиента, может быть нежелательно оставлять подобные изменения в базе данных клиентов.

Это решение вдохновлено пост Андреаса Щербаума .

-- 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();
ответил zpon 18 WedEurope/Moscow2013-12-18T13:06:34+04:00Europe/Moscow12bEurope/MoscowWed, 18 Dec 2013 13:06:34 +0400 2013, 13:06:34
0

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'
  );
ответил Szymon Lipiński 19 42009vEurope/Moscow11bEurope/MoscowThu, 19 Nov 2009 23:21:23 +0300 2009, 23:21:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132