Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在postgres中,使用规则在两个表之间拆分更新_Sql_Postgresql_Rules - Fatal编程技术网

Sql 在postgres中,使用规则在两个表之间拆分更新

Sql 在postgres中,使用规则在两个表之间拆分更新,sql,postgresql,rules,Sql,Postgresql,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 ); 更新后,希望更新t1并插入到编辑批次中 update t1

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

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 );
更新后,希望
更新t1
插入到编辑批次中

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;
如何为此制定规则?

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

测试设置 创建触发函数 创建触发器 试验 清理 评论 规则很难或完全不可能(取决于设置的细节)确定哪些行被更新


A可以事后决定,是更好的选择。在这种情况下,还可以轻松地与(大多数)其他触发器和/或规则集成。

也可以使用其他规则进行集成,只需尝试即可。不要忘记日志表的PK将是{id,edit_ts}。插入操作应始终检查日志表中的“不存在”。删除有点特别。并始终检查生成的查询计划。右-规则规则(原样)。但是如何处理任意数量的列呢?因为您只记录事件(而不记录数据),所以任意列并不重要。记录被更新(插入、删除)命中或未命中。也许我不明白你的意思?正如你所描述的,目前正在使用触发器。但是试图通过将
editor\u id
作为更新表的一部分来避免欺骗。@cYoung:如果
editor\u id
可以从或
session\u user
派生,则更新表中不需要额外的列。扳机不是骗局。这是典型的解决方案。与大多数web应用一样,所有普通用户都共享db用户名。由于pg连接非常昂贵,这是有意义的。pg不知道应用程序用户。作弊者必须在更新表中维护
editor\u id
列,而不是使用触发器。使用规则而不是触发器背后的想法是试图绕过这个骗局。
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.