【发布时间】:2011-10-11 22:59:43
【问题描述】:
假设我有下表:
create table A
(
identifier integer not null primary key,
title text not null,
... -- other fields
);
在 A 上执行 UPDATE 时,我不一定只想更新目标行,但我也想将更新应用到 A 中的另一行。我尝试编写“重写规则”或“触发器之前”,但我总是以无限循环结束:
create function A(in A, in A) returns void as
$$
declare
i integer;
begin
-- do some logic which finds other row (hardcoded in this example)
i = 2;
-- update old row
update A set title = $2.title where identifier = $1.identifier;
-- apply updates to other row
update A set ... where identifier = i;
end;
$$ language plpgsql;
create rule A as on update to A do instead select A(old, new);
我测试的数据:
insert into A (identifier, title) values (1, 'old title 1');
insert into A (identifier, title) values (2, 'old title 2');
update A set title = 'new title 1' where identifier = 1;
使用“之前触发器”而不是“重写规则”时也会出现同样的问题。
如果需要,有没有办法绕过规则/触发器?我无法在第一行之后更改表 A 禁用规则 A,并且在返回之前更改表 A 启用规则 A,因为我们自己正在使用表 A。
更新
我设法通过创建一个在其上完成“内部更新”的虚拟继承表来做到这一点,而不是直接在表上。这绕过了触发器/规则。
drop table if exists A cascade;
create table A
(
identifier serial not null primary key,
title text not null
);
create table A_
(
) inherits (A);
create or replace function A() returns trigger as
$$
declare
i integer;
begin
-- create duplicate row
insert into A (title) values (new.title) returning identifier into i;
-- update new row
update A_ set title = new.title where identifier = i;
-- do not propagate update
return null;
end
$$ language plpgsql;
create trigger A before update on A for each row execute procedure A();
insert into A (title) values ('old title 1');
insert into A (title) values ('old title 2');
update A set title = 'new title 1' where identifier = 1;
select * from A;
【问题讨论】:
标签: postgresql triggers rules infinite-loop