LoginSignup
2
2

More than 3 years have passed since last update.

postgresqlのtrigger によるユニークチェック

Posted at

postgesqlでは、unique indexによってユニーク制約できますが、
値の一部(例:timestampの日付部分)でユニーク制約したい場合、
unique index では対応できません。
この場合は、trigger を利用する必要があります。

以下のtest テーブルを例とします。


CREATE TABLE public.test
(
    id integer NOT NULL,
    name text COLLATE pg_catalog."default" NOT NULL,
    age integer NOT NULL,
    created_at timestamp with time zone NOT NULL
)

同じ日付でname,ageも同じレコードを insert するとエラーにしたい場合、以下のトリガーを定義します。

まず、トリガー用の function を定義します。
対象レコードがすでに存在する場合、unique_violation を発生するようにします。


CREATE OR REPLACE FUNCTION trigger_unique_check_func()
 RETURNS TRIGGER
 LANGUAGE PLPGSQL
 AS
 $$
BEGIN
    IF EXISTS (SELECT name from test WHERE name = NEW.name
                and age = NEW.age
                and created_at::date = NEW.created_at::date ) THEN
        RAISE EXCEPTION unique_violation;
    END IF;
    RETURN NEW;
END $$;

次は、トリガーを定義します。


CREATE  TRIGGER trigger_unique_check
BEFORE INSERT
ON test
FOR EACH ROW
EXECUTE PROCEDURE trigger_unique_check_func();

試験:
まず、以下のSQLを実行します。


INSERT INTO test VALUES(1, 'a', 1, '2020-12-02 13:14:15');

結果:

INSERT 0 1

最初は、対象レコードがまだテーブルに存在しないので、
無地にinsert できました。

次に、以下のSQLを実行します


INSERT INTO test VALUES(2, 'a', 1, '2020-12-02 13:14:15');

結果

ERROR:  unique_violation
CONTEXT:  PL/pgSQL 関数 trigger_unique_check_func() の6行目 - RAISE
SQL state: 23505

オー、ちゃんっとエラーでました!
以上です。
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2