PgSQL日志表更新时间

时间:2014-05-02 11:11:13

标签: postgresql triggers updates

我创建了下表:

CREATE TABLE updates
(
  "table" text,
  last_update timestamp without time zone
)

我想在任何表更新时更新它,问题是我不知道怎么样,有人可以帮我把这个伪代码变成触发器吗?

this = current table on whitch operation is performed
ON ALTER,INSERT,DELETE {
  IF (SELECT COUNT(*) FROM updates where table = this) = 1
  THEN 
    UPDATE updates SET  last_update = timeofday()::timestamp WHERE `table`=this
  ELSE
    INSERT INTO updates VALUES (this,timeofday()::timestamp);
}

1 个答案:

答案 0 :(得分:1)

您需要一个触发器函数,只要您的某个表被“更新”,就会调用它,假设您的意思是成功执行了INSERTUPDATEDELETE。该触发器功能如下所示:

CREATE FUNCTION log_update() RETURNS trigger AS $$
BEGIN
  UPDATE updates SET last_update = now() WHERE "table" = TG_TABLE_NAME;
  IF NOT FOUND THEN
    INSERT INTO updates VALUES (TG_TABLE_NAME, now());
  END IF;
  IF (TG_OP = 'DELETE') THEN
    RETURN OLD;
  ELSE
    RETURN NEW;
  END IF;
END; $$ LANGUAGE PLPGSQL;

每个必须以这种方式记录的表都需要有一个与之关联的触发器,如下所示:

CREATE TRIGGER ZZZ_mytable_log_updates
AFTER INSERT OR UPDATE OR DELETE ON mytable
FOR EACH ROW EXECUTE PROCEDURE log_update();

一些评论:

  • 使用PL / PgSQL创建触发器功能;请参阅文档中的第40章。触发功能带有一些自动参数,例如TG_TABLE_NAME
  • 不要使用保留字(在您的情况下为“table”)作为列名。实际上,在这种情况下,最好使用表格的oid,并使用相关的TG_RELID自动参数。它占用的存储空间更少,速度更快,并且避免了数据库的不同模式中具有相同名称的表之间的混淆。您可以使用pg_tables系统目录表从oid中查找表名。
  • 您必须根据操作返回正确的值,否则操作可能会失败。 INSERTUPDATE操作需要返回NEW; DELETE需要OLD返回。
  • 触发器的名称以“ZZZ”开头,以确保在同一个表上的任何其他触发器成功后触发它(它们按字母顺序触发)。如果先前的触发器失败,则不会调用此触发器函数,这是正确的行为,因为插入,更新或删除也不会发生。