Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.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
postgresql中update语句后未激发规则_Postgresql_Rules - Fatal编程技术网

postgresql中update语句后未激发规则

postgresql中update语句后未激发规则,postgresql,rules,Postgresql,Rules,遵循 我创建了以下语句: CREATE TABLE shoelace_log ( sl_name text, -- shoelace changed sl_avail integer, -- new available value log_who text, -- who did it log_when timestamp -- when); CREATE RULE log_shoelace AS ON UPDATE

遵循

我创建了以下语句:

CREATE TABLE shoelace_log (
sl_name    text,          -- shoelace changed
sl_avail   integer,       -- new available value
log_who    text,          -- who did it
log_when   timestamp      -- when);
CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data
WHERE NEW.sl_avail <> OLD.sl_avail
DO INSERT INTO shoelace_log VALUES (
                                NEW.sl_name,
                                NEW.sl_avail,
                                current_user,
                                current_timestamp
                            );
只执行更新查询,不触发规则。我尝试使用命令解释原因

EXPLAIN UPDATE shoelace_log SET sl_avail = 6 WHERE sl_name = 'sl7';
日志上写着:

"Seq Scan on shoelace_log  (cost=0.00..19.66 rows=4 width=32)"
"  Filter: (sl_name = 'sl7'::text)"
"Seq Scan on shoelace_log  (cost=0.00..19.62 rows=4 width=78)"
"  Filter: (sl_name = 'sl7'::text)"

我也尝试在EXPLAIN中使用VERBOSE选项,但我不明白为什么没有触发我的事件。

您选择了错误的功能。完全忘记规则吧——它们很难做到,几乎不可能做到正确

您需要的是一个触发器:

create or replace function shoelace_log_who_when()
returns trigger language plpgsql as
$$
begin
  if OLD.sl_avail is distinct from NEW.sl_avail then
    NEW.log_who = current_user;
    NEW.log_when = current_timestamp;
  end if;
  return NEW;
end;
$$;

create trigger shoelace_log_who_when before update on shoelace_log
  for each row execute procedure shoelace_log_who_when();
试试看:

insert into shoelace_log values ( 'foo', 1, NULL, NULL ); select * from shoelace_log;

您可能还想考虑使用预构建的ADON为您这样做:


我试过这个例子,它奏效了。但我必须先创建鞋带数据表。该表不在示例中

create table shoelace_data (
    sl_name text,
    sl_avail integer
);
insert into shoelace_data values ('Catcall', 3);
update shoelace_data set sl_avail = 5;
现在,如果您从日志表中选择

select * from shoelace_log;
"Catcall";5;"postgres";"2011-03-31 20:40:10.906"

请注意,规则规定,当鞋带数据中的sl_avail列有更新时,应插入鞋带日志。

它不是tablelog。这只是为了在表中填写自动上次修改的时间戳和用户。我尝试在pg9上运行您链接到的示例,但遇到了相同的问题。您说您的pgAdmin3查询是UPDATE shoelace_data,但您解释了UPDATE shoelace_log日志表。。。你确定你正在键入你认为正在键入的查询吗?+1是一个很好的答案,但仍然不能解释为什么这样一个简单的示例不起作用。这就是为什么你不应该使用规则。它们非常复杂,即使是经验丰富的博士后用户也不会试图解释他们的行为。我认为他们被认为是被开除了博士后;在9.1版本中,视图上的INSTEAD OF触发器不再需要它们了。可惜pg文档没有声明不应该使用它们。我已经阅读了一些原因,说明它们是痛苦的,应该避免,但并不是因为它们没有文档所描述的功能。OP混淆了数据表和日志表——他想在以某种方式更新前者时插入后者。你需要一个不同的触发程序。重新阅读问题,在解释混淆之前停下来。。。 update shoelace_log set sl_avail=2; select * from shoelace_log; sl_name | sl_avail | log_who | log_when ---------+----------+----------+--------------------------- foo | 2 | tometzky | 2011-03-30 17:06:21.07137
create table shoelace_data (
    sl_name text,
    sl_avail integer
);
insert into shoelace_data values ('Catcall', 3);
update shoelace_data set sl_avail = 5;
select * from shoelace_log;
"Catcall";5;"postgres";"2011-03-31 20:40:10.906"