繁体   English   中英

在postgres中,使用Rule在两个表之间拆分更新

[英]in postgres, splitting an update between two tables using Rules

尝试使用规则维护编辑日志。

create table t1(
    id serial primary key,
    c1 text,
    ... );

create table edit_log(
    id int references t1,
    editor_id int references users,
    edit_ts timestamp default current_timestamp );

更新后,希望update t1insert into edit_lot

update t1 set c1='abc', ... where id=456;
insert into edit_log( id, editor_id, current_timestamp );

除了任意数量的列,这将非常简单明了,例如,

update t1 set c1='abc', c2='def', editor_id=123 where id=456;
update t1 set c3='xyz', editor_id=123 where id=456;

怎么写规则呢?

我认为触发器比规则更能为您服务。 考虑这个演示。

测试设置

CREATE TEMP TABLE t1(id int, editor_id int, c1 text);
INSERT INTO t1(id, editor_id) VALUES (1,1),(2,2);
CREATE TEMP TABLE edit_log(id int, editor_id int, edit_ts timestamp);

创建触发功能

CREATE OR REPLACE FUNCTION trg_t1_upaft_log()
  RETURNS trigger AS
$BODY$
BEGIN

IF OLD IS DISTINCT FROM NEW THEN -- to avoid empty updates
    INSERT INTO edit_log(id, editor_id, edit_ts)
    VALUES(NEW.id, NEW.editor_id, now()::timestamp);
END IF;

RETURN NULL; -- trigger will be fired AFTER updates, return value is irrelevant.

END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

创建触发器

CREATE TRIGGER upaft_log
  AFTER UPDATE ON t1
  FOR EACH ROW
  EXECUTE PROCEDURE trg_t1_upaft_log();

测试

UPDATE t1 SET c1 = 'baz' WHERE id = 1;
SELECT * FROM edit_log; -- 1 new entry

UPDATE t1 SET c1 = 'baz' WHERE id = 1;
SELECT * FROM edit_log;  -- no new entry, update changed nothing!

UPDATE t1 SET c1 = 'blarg';
SELECT * FROM edit_log;  -- 2 new entries, update changed two rows.

清理

DROP TRIGGER upaft_log ON t1;
DROP FUNCTION trg_t1_upaft_log()
-- Temp. tables will be dropped automatically at end of session.

评论

根据规则确定要更新的行是非常困难或完全不可能的(取决于安装程序的详细信息)。

触发AFTER UPDATE可以根据实际情况决定,是更好的选择。 在这种情况下,还易于与(大多数)其他触发器和/或规则集成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM