Подтвердить что ты не робот

Postgres: добавить ограничение, если оно еще не существует

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

4b9b3361

Ответ 1

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

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, на самом деле вы не хотите, чтобы вы сбрасывали ограничения волей-неволей. Даже в течение нескольких миллисекунд есть короткое окно, в котором вы больше не применяете свое ограничение, которое может позволить пропустить ошибочные значения. Это может иметь непреднамеренные последствия, ведущие к значительным расходам на бизнес в какой-то момент в будущем.

Ответ 2

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

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

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

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

Ответ 3

Вы можете использовать обработчик исключений внутри анонимного блока 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

Ответ 4

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

SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'"

Ответ 5

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

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

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$$; 

Ответ 6

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

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
$$;

Ответ 7

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

- SELECT "Column1" , "Column2" , "Column3" , count (star) FROM dbo. "MyTable" GROUP BY "Column1" , "Column2" , "Column3" HAVING count (*) > 1;

alter table dbo. Ограничение календаря "MyTable" , если существует "MyConstraint_Name";

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