如何在PostgreSQL中自动更新时间戳


132

我希望代码能够像在MySQL中使用CURRENT_TIMESTAMP一样在插入新行时自动更新时间戳。

如何在PostgreSQL中实现这一目标?

CREATE TABLE users (
    id serial not null,
    firstname varchar(100),
    middlename varchar(100),
    lastname varchar(100),
    email varchar(200),
    timestamp timestamp
)

6
顺便说一下,timestampSQL规范将您的数据类型定义为的缩写TIMESTAMP WITHOUT TIME ZONE。正如Postgres专家David E. Wheeler解释的那样,这几乎肯定不是您想要的。另一种类型TIMESTAMP WITH TIME ZONE可能是您想要的类型,它使用任何传递的时区偏移信息来将日期时间调整为UTC(尽管类型名实际上并未存储该时区信息)。
罗勒·布尔克

3
重新学习了这一点之后,我写了一篇详细的博客文章,内容涉及使用默认值,函数和触发器记录行创建和修改的日期时间。包括完整的示例SQL和PL / pgSQL代码,供Postgres使用。
罗勒·布尔克

Answers:


197

要在插入过程中填充列,请使用一个DEFAULT值:

CREATE TABLE users (
  id serial not null,
  firstname varchar(100),
  middlename varchar(100),
  lastname varchar(100),
  email varchar(200),
  timestamp timestamp default current_timestamp
)

请注意,可以通过在INSERT语句中提供值来显式覆盖该列的值。如果要防止这种情况,则需要触发器

如果每当行更新时也需要更新该列,则还需要一个触发器(如EJ Brennan所述

请注意,对于列名使用保留字通常不是一个好主意。您应该找到与以下名称不同的名称timestamp


14
要知道,Postgres有功能要告诉你(1)实际的当前时刻的时间;(2)启动语句的时间,以及(3)交易开始的时间。此处显示的示例是当前交易的开始。与其他两种可能性相反,您可能想要也可能不想要。
罗勒·布尔克

6
关于避免与保留字冲突的名称的好处。请注意,SQL规范明确承诺不要将结尾的下划线用作保留字。这样就可以制作timestamptimestamp_。更好的是更具描述性的名称,例如row_created_
罗勒·布尔克

尽管后半部分提到了其他答案(是正确的),但前半部分根本不是OP要求的,但这仍然令人误解。这不应该作为答案。
埃里克·王

1
在类型的Postgres文档中这样说。Varchar有额外的CPU周期来检查约束,这在TEXT上不会发生。
拉赫利

3
没有单个字段,但是我从未见过有用的带有单个字段的表。该约束因字段数而更加复杂。我记得将表中的所有varchar都更改为文本,并将写作效率提高了15%。同样,小的性能损失也不是“ NO”性能损失。
拉赫利

104

您需要编写一个插入触发器,如果​​要在记录更改时对其进行更改,则可能需要一个更新触发器。这篇文章很好地解释了它:

http://www.revsys.com/blog/2006/aug/04/automatically-updating-a-timestamp-column-in-postgresql/

CREATE OR REPLACE FUNCTION update_modified_column()   
RETURNS TRIGGER AS $$
BEGIN
    NEW.modified = now();
    RETURN NEW;   
END;
$$ language 'plpgsql';

像这样应用触发器:

CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON customer FOR EACH ROW EXECUTE PROCEDURE  update_modified_column();

2
这是IMO的最佳答案(尽管默认值足以插入)。
kik

2
这里有什么新消息?
Naveen


这是一个更完整的解决方案,可以与初始INSERT以及任何后续UPDATE(适用于数据审核)一起使用。当然,OP仅要求提供前者。
Pavel Lechev

5
@Naveen不太多,您有什么新消息?
Underyx

57

仅当值更改时才更新时间戳

基于EJ的链接并从该链接添加if语句(https://stackoverflow.com/a/3084254/1526023

CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
   IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN
      NEW.modified = now(); 
      RETURN NEW;
   ELSE
      RETURN OLD;
   END IF;
END;
$$ language 'plpgsql';

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.