Есть ли у Postgres какой-либо способ сказать ALTER TABLE foo ADD CONSTRAINT bar ...
, который просто проигнорирует команду, если ограничение уже существует, чтобы оно не вызывало ошибку?
Postgres: добавить ограничение, если оно еще не существует
Ответ 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" );