2017-06-07 6 views
3

を動作するように別のものを防ぎ、我々が持っていると仮定します。PostgreSQLのトリガーは

create table T 
(
    id bigserial primary key 
    , a int 
    , b int 
    , c int 
); 

私はcはいつもa+bに等しく、私はcの手動変更を防止したいようにしたいです。私が行う場合

-- Prevents manual changes of c: 

create or replace function no_changes() returns trigger as $$ 
begin 
    if old.c is distinct from new.c then 
     raise exception 'Can''t change c manually.'; 
    end if; 
    return new; 
end; 
$$ language plpgsql; 

create trigger no_changes 
before update of c -- 'before' so prevents changes in 'c' 
on T 
for each row 
execute procedure no_changes(); 

-- Do c = a + b: 

create or replace function change() returns trigger as $$ 
begin 
    update T 
    set c = a + b 
    where id = new.id; 
    return new; 
end; 
$$ language plpgsql; 

create trigger change 
after insert or update of a, b -- 'after' so I'm sure the row is inserted/updated 
on T 
for each row 
execute procedure change(); 

update T set c = 247; 

私はエラーメッセージが表示される「C手動で変更できません」と列は変更を行いませんので、私は2つのトリガーを作成します。すばらしいです。私が行う場合

はしかし、:

insert into T (a, b) values (4, 3); 

または:

update T set a = 3 where id = 2 -- suppose id = 2 exists 

をそれから私は前と同じエラーメッセージが表示されます。明らかに、updateコマンドのchangeトリガーがno_changesトリガーを起動し、c列の更新を防止します。

アイデア?ありがとう!

答えて

4

全体ロジックは、単一の関数に配置することができます

create or replace function change() returns trigger as $$ 
begin 
    if old.c is distinct from new.c then 
     raise exception 'Can''t change c manually.'; 
    end if; 
    new.c := new.a + new.b; 
    return new; 
end; 
$$ language plpgsql; 

create trigger change 
before insert or update on T 
for each row 
execute procedure change(); 

しかし、あなたは、ロジックを分割することを好む場合は、
1)beforeイベント
2の両方のトリガーを作成します)"If multiple triggers of the same kind are defined for the same event, they will be fired in alphabetical order by name."名前がにトリガのでctrg2_changeの変更がcの値を計算しないように、希望の順序を取得します(たとえば、trg1_check)。

+0

ありがとう、@アベリスト。両方のトリガーを 'before'トリガーにする必要がありますか?代わりに 'after'トリガを使用することはできませんか? –

+1

@RicardoPérezLópezできます。しかし、 'after'トリガで' NEW'変数を使って挿入/更新された行を変更することはできません(コードの主な問題です。 'update'は' before update'トリガを発生させます)。 – Abelisto

関連する問題