我们的一个名为rep_event的Postgres表有一个时间戳列,指示每行插入的时间。但是所有行的时间戳值都是2000-01-01 00:00:00,所以没有正确的设置。
有一个函数可以在表中插入行,它是唯一一个将行插入该表的代码 - 没有其他代码插入到该表中。 (也没有任何代码可以更新该表中的行。)以下是函数的定义:
CREATE FUNCTION handle_event() RETURNS "trigger"
AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO rep_event SELECT 'D', TG_RELNAME, OLD.object_id, now();
RETURN OLD;
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO rep_event SELECT 'U', TG_RELNAME, NEW.object_id, now();
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO rep_event SELECT 'I', TG_RELNAME, NEW.object_id, now();
RETURN NEW;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
以下是表格定义:
CREATE TABLE rep_event
(
operation character(1) NOT NULL,
table_name text NOT NULL,
object_id bigint NOT NULL,
time_stamp timestamp without time zone NOT NULL
)
如您所见,调用now()函数来获取当前时间。在数据库上执行“select now()”会返回正确的时间,因此在函数内调用now()会有问题吗?
答案 0 :(得分:4)
更简单的解决方案是只修改表定义以使NOW()成为默认值:
CREATE TABLE rep_event (
operation character(1) NOT NULL,
table_name text NOT NULL,
object_id bigint NOT NULL,
time_stamp timestamp without time zone NOT NULL DEFAULT NOW()
);
然后你可以摆脱触发器中的now()调用。
另外作为附注,我强烈建议在你的函数中加入列排序...... IOW;
INSERT INTO rep_event (operation,table_name,object_id,time_stamp) SELECT ...
这样,如果您添加新列或进行其他表更改以更改表的内部顺序,则您的函数不会突然中断。
答案 1 :(得分:1)
你的问题必须在别的地方,因为你的功能很好。创建测试数据库,粘贴您引用的代码并运行:
create table events (object_id bigserial, data text);
create trigger rep_event
before insert or update or delete on events
for each row execute procedure handle_event();
insert into events (data) values ('v1'),('v2'),('v3');
delete from events where data='v2';
update events set data='v4' where data='v3';
select * from events;
object_id | data -----------+------ 1 | v1 3 | v4
select * from rep_event;
operation | table_name | object_id | time_stamp -----------+------------+-----------+---------------------------- I | events | 1 | 2011-07-08 10:31:50.489947 I | events | 2 | 2011-07-08 10:31:50.489947 I | events | 3 | 2011-07-08 10:31:50.489947 D | events | 2 | 2011-07-08 10:32:12.65699 U | events | 3 | 2011-07-08 10:32:33.662936 (5 rows)
检查其他触发器,触发创建命令等。并将此timestamp without timezone
更改为timestamp with timezone
。