在函数中调用now()

时间:2011-07-07 23:08:53

标签: postgresql timestamp

我们的一个名为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()会有问题吗?

2 个答案:

答案 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