假设我们有:
我想让 c 始终等于
如果我这样做:
我看到了错误信息 "无法手动更改 c",而且列没有发生变化。很好。
但是,如果我执行以下操作:
然后我收到与之前相同的错误消息。显然,“更改”触发器中的“更新”命令会触发“无更改”触发器,从而阻止对“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;
我看到了错误信息 "无法手动更改 c",而且列没有发生变化。很好。
但是,如果我执行以下操作:
insert into T (a, b) values (4, 3);
或者:
update T set a = 3 where id = 2 -- suppose id = 2 exists
然后我收到与之前相同的错误消息。显然,“更改”触发器中的“更新”命令会触发“无更改”触发器,从而阻止对“c”列的更新。
有任何想法吗?谢谢!
after
触发器中使用“NEW”变量更改插入/更新的行(这是您代码的主要问题,“update”会引发“before update”触发器)。 - Abelisto