PostgresにはALTER TABLE foo ADD CONSTRAINT bar ...
制約が既に存在する場合、エラーを発生させないようにコマンドを無視しますか?
これは役立つかもしれませんが、少し汚いハックかもしれません:
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 ...;
開発データベースではおそらく問題ありません。または、メンテナンスウィンドウをこのデータベースに依存しているアプリをシャットダウンできることがわかっている場合は、おそらく問題ありません。
しかし、これが24時間365日稼働するミッションクリティカルな実稼働環境である場合、このように無制限に制約を削除することは望ましくありません。数ミリ秒でも、誤った値がすり抜けられる可能性のある制約を強制しなくなった短いウィンドウがあります。これは、将来のある時点でかなりのビジネスコストにつながる意図しない結果をもたらす可能性があります。
可能な解決策は、新しい制約を作成する前にDROP IF EXISTSを使用するだけです。
ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;
Information_schemaまたはカタログを照会するよりも簡単に見えますが、常に制約を再作成するため、巨大なテーブルでは時間がかかる場合があります。
編集2015-07-13:Kevは his answer で、制約が存在せず強制されていない場合にソリューションが短いウィンドウを作成することを指摘しました。これは事実ですが、トランザクションで両方のステートメントをラップすることにより、このようなウィンドウを非常に簡単に回避できます。
匿名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.htmlhttp://www.postgresql.org/docs/9.4/static/plpgsql- control-structures.htmlhttp://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
pg_constraint
tableに対してクエリを実行して、制約の有無を確認できます。
SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'"
制約を作成することは、大量のデータを含むテーブルに対してコストのかかる操作になる可能性があるため、すぐに再作成するためだけに制約を削除しないことをお勧めします。
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$$;