PostgreSQL 触发器阻止另一个触发器工作
PostgreSQL trigger prevents another one to work
假设我们有:
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;
我看到错误消息 "Can't change c manually" 并且该列没有更改。太好了。
但是,如果我这样做:
insert into T (a, b) values (4, 3);
或:
update T set a = 3 where id = 2 -- suppose id = 2 exists
然后我得到了和以前一样的错误信息。显然,来自 change
触发器的 update
命令触发 no_changes
触发器阻止 c
列中的更新。
有什么想法吗?谢谢!
整个逻辑可以放在一个函数中:
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."所以name触发得到想要的顺序,例如trg1_check
来防止c
和trg2_change
的变化来计算c
值。
假设我们有:
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;
我看到错误消息 "Can't change c manually" 并且该列没有更改。太好了。
但是,如果我这样做:
insert into T (a, b) values (4, 3);
或:
update T set a = 3 where id = 2 -- suppose id = 2 exists
然后我得到了和以前一样的错误信息。显然,来自 change
触发器的 update
命令触发 no_changes
触发器阻止 c
列中的更新。
有什么想法吗?谢谢!
整个逻辑可以放在一个函数中:
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."所以name触发得到想要的顺序,例如trg1_check
来防止c
和trg2_change
的变化来计算c
值。