Postgres: добавить ограничение, если оно еще не существует - PullRequest
50 голосов
/ 23 июля 2011

Есть ли у Postgres какой-либо способ сказать ALTER TABLE foo ADD CONSTRAINT bar ..., который будет просто игнорировать команду, если ограничение уже существует, чтобы не вызывать ошибку?

Ответы [ 7 ]

62 голосов
/ 20 августа 2014

Возможное решение - просто использовать DROP IF EXISTS перед созданием нового ограничения.

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;

Кажется проще, чем пытаться запрашивать информационную схему или каталоги, но может быть медленным для больших таблиц, так как оно всегда воссоздает ограничение.

Редактировать 2015-07-13: Кев указал в своем ответе , что мое решение создает короткое окно, когда ограничение не существует и не применяется. Хотя это и так, вы можете легко избежать такого окна, заключив оба оператора в транзакцию.

32 голосов
/ 24 июля 2011

Это может помочь, хотя это может быть немного грязным взломом:

create or replace function create_constraint_if_not_exists (
    t_name text, c_name text, constraint_sql text
) 
returns void AS
$$
begin
    -- Look for our constraint
    if not exists (select constraint_name 
                   from information_schema.constraint_column_usage 
                   where table_name = t_name  and constraint_name = c_name) then
        execute constraint_sql;
    end if;
end;
$$ language 'plpgsql'

Затем вызовите с:

SELECT create_constraint_if_not_exists(
        'foo',
        'bar',
        'ALTER TABLE foo ADD CONSTRAINT bar CHECK (foobies < 100);')

Обновлено:

В соответствии с ответом Webmut ниже с предложением:

ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;

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

Но если это живая критически важная производственная среда 24x7, то вам не стоит отказываться от подобных ограничений.Даже на несколько миллисекунд есть короткое окно, в котором вы больше не применяете ограничение, которое может позволить ошибочным значениям проскальзывать.Это может иметь непредвиденные последствия, приводящие к значительным издержкам бизнеса в какой-то момент в будущем.

18 голосов
/ 11 сентября 2015

Вы можете использовать обработчик исключений внутри анонимного блока DO, чтобы поймать ошибку дублирующегося объекта.

DO $$
BEGIN

  BEGIN
    ALTER TABLE foo ADD CONSTRAINT bar ... ;
  EXCEPTION
    WHEN duplicate_object THEN RAISE NOTICE 'Table constraint foo.bar already exists';
  END;

END $$;

http://www.postgresql.org/docs/9.4/static/sql-do.html http://www.postgresql.org/docs/9.4/static/plpgsql-control-structures.html http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html

9 голосов
/ 23 июля 2011

Вы можете выполнить запрос к таблице pg_constraint, чтобы найти, существует ограничение или нет. Как:

SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'"
5 голосов
/ 21 июля 2017

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

Я решил решить эту проблему с помощью блока анонимного кода, очень похожего на Майка Станковича, однако в отличие от Майка (который обнаруживает ошибку), я сначала проверяю, существует ли ограничение:

DO $$
BEGIN
    IF NOT EXISTS ( SELECT  constraint_schema
                ,       constraint_name 
                FROM    information_schema.check_constraints 
                WHERE   constraint_schema = 'myschema'
                  AND   constraint_name = 'myconstraintname'
              )
    THEN
        ALTER TABLE myschema.mytable ADD CONSTRAINT myconstraintname CHECK (column <= 100);
    END IF;
END$$; 
0 голосов
/ 08 мая 2019

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

DO 
$$ BEGIN
IF NOT EXISTS (select constraint_name 
               from information_schema.table_constraints 
               where table_schema='schame_name' and upper(table_name) = 
upper('table_name')  and upper(constraint_name) = upper('constraint_name'))

THEN

   ALTER TABLE TABLE_NAME ADD CONSTRAINT CONTRAINT_NAME..... ;

ELSE raise NOTICE 'Constraint CONTRAINT_NAME already exists in Table TABLE_NAME';   

END IF;
END
$$;
0 голосов
/ 03 июня 2014

Не знаете, почему столько строк кода?

- ВЫБЕРИТЕ "Column1", "Column2", "Column3", count (star) FROM dbo. "MyTable" GROUP BY "Column1", "Column2", "Column3" HAVING count (*)> 1;

изменить таблицу dbo. "MyTable" удалить ограничение, если существует "MyConstraint_Name";

ALTER TABLE dbo. "MyTable" ADD CONSTRAINT "MyConstraint_Name" UNIQUE ("Column1", "Column3", "Column2");

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...