postgresql设置自动更新时间方法

Posted win_zcj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了postgresql设置自动更新时间方法相关的知识,希望对你有一定的参考价值。

  • 在我们日常开发中,在设计数据库字段的时候不可避免的都要created_time(创建时间)以及updated_time(修改时间)两个时间戳字段,作用大家也都一目了然。下面将为大家详细介绍两个字段的如何去设置来达到你想要的那个样子.我将用Navicat以及sql语句来大家详细介绍

一、created_time

首先是created_time,我们可以通过Navicat在添加字段时候将字段设置为timestamp类型,生成时间戳方式为CURRENT_TIMESTAMP或者设置为now()
至于SQL语句只需在建表过程default 一下就行这里不做赘述。

二、updated_time

接下来是updated_time,也就是我们本篇文章的重点,相信你已经找遍了度娘还没解决吧,没关系,我来帮你解决。

postgresql更新时间戳需要通过触发器来实现,至于有没有其他方式,我暂时还没找到。

1、首先需要通过代码创建函数,也就是定义触发器

CREATE OR REPLACE FUNCTION "public"."cs_timestamp"()
  RETURNS "pg_catalog"."trigger" AS $BODY$
begin
    new.updated_time= current_timestamp;
    return new;
end
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

cs_timestamp():为你定义函数的名称。
updated_time:为你表中更新时间戳字段名称(pgsql不可以大写的)。
其他的不用管执行就可以了。此过程只能通过sql实现.

2、接下来就是创建触发器了

create trigger cs_name before update on student for each row execute procedure cs_timestamp();

cs_name:触发器名称,可以随意设置,但是不要设置成中文的。
student:表名
cs_timestamp():触发器所要用的函数名称,与第一步函数名称保持一致。

django开发我给它写到了迁移文件里面了:

此过程可以通过Navicat设置,我用的是Navicat15,大家仅供参考

结尾:当然函数可以在建好表后定义,也可以在建表前定义,这里无伤大雅。

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

【中文标题】如何在 PostgreSQL 中自动更新时间戳【英文标题】:How do I automatically update a timestamp in PostgreSQL 【发布时间】:2012-03-22 07:47:05 【问题描述】:

我希望代码能够在插入新行时自动更新时间戳,就像我在 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
)

【问题讨论】:

顺便说一下,你的timestamp数据类型是由SQL规范定义为TIMESTAMP WITHOUT TIME ZONE的缩写。这几乎肯定不是你想要的,就像explained by Postgres expert David E. Wheeler。另一种类型,TIMESTAMP WITH TIME ZONE 可能是您想要的,使用任何传递的时区偏移信息将日期时间调整为 UTC(但实际上并没有存储该时区信息,尽管类型名称)。 在重新学习了这一点之后,我写了一个detailed blog post,关于使用默认值、函数和触发器记录行的创建和修改的日期时间。包括用于 Postgres 的完整示例 SQL 和 PL/pgSQL 代码。 【参考方案1】:

要在插入期间填充列,请使用 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 语句中提供值来显式覆盖。如果您想防止这种情况发生,您确实需要trigger。

如果您需要在更新行时更新该列(如mentioned by E.J. Brennan),则还需要一个触发器

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

【讨论】:

请注意 Postgres 有 functions 告诉您 (1) 实际当前时刻的时间,(2) 语句开始的时间,以及 (3) 事务开始的时间。此处显示的示例是当前事务的开始。与其他两种可能性相反,您可能想要也可能不想要。 避免名称与保留字冲突的好处。请注意,SQL 规范明确承诺永远不会使用结尾的下划线作为保留字。所以你可以把timestamp变成timestamp_。更好的是一个更具描述性的名称,例如row_created_ 前半部分根本不是OP所要求的,尽管后半部分提到了其他答案(这是正确的),但它仍然具有误导性。这不应该被接受为答案。 在类型的 Postgres 文档中这样说。 Varchar 有额外的 CPU 周期来检查约束,这在 TEXT 上不会发生。 没有单个字段,但我从未见过有单个字段的有用表格。该约束因字段数量而更加复杂。我记得将表格中的所有 varchar 更改为文本并获得了 15% 的写作改进。此外,小的性能损失不是“否”性能损失。【参考方案2】:

您需要编写一个插入触发器,如果​​您希望在更改记录时更改它,还可能编写一个更新触发器。这篇文章解释得很好:

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();

【讨论】:

这是一个更完整的解决方案,适用于初始 INSERT 以及任何后续 UPDATE(有利于数据审计)。当然,OP 只要求前者。【参考方案3】:

更新时间戳,仅当值发生变化时

基于 E.J 的链接并从此链接添加 if 语句 (https://***.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';

【讨论】:

【参考方案4】:

使用 'now()' 作为默认值会自动生成时间戳。

【讨论】:

仅用于添加值,更新记录时似乎不使用默认值。【参考方案5】:

要在插入新行时自动更新 PostgresSQL 中的时间戳字段,您可以将 current_timestamp 设置为其 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
)

除此之外,您可能希望阻止任何人在将来更新此字段,这可以通过创建更新触发器并应用它来完成:

CREATE OR REPLACE FUNCTION stop_change_on_timestamp()
  RETURNS trigger AS
$BODY$
BEGIN
  -- always reset the timestamp to the old value ("actual creation time")
  NEW.timestamp := OLD.timestamp;
  RETURN NEW;
END;
$BODY$
CREATE TRIGGER prevent_timestamp_changes
  BEFORE UPDATE
  ON users
  FOR EACH ROW
  EXECUTE PROCEDURE stop_change_on_timestamp();

【讨论】:

【参考方案6】:

对于更新和 Liquibase YAML:

databaseChangeLog:
  - changeSet:
      id: CREATE FUNCTION set_now_to_timestamp
      author: Konstantin Chvilyov
      changes:
        - sql:
            sql: CREATE OR REPLACE FUNCTION set_now_to_timestamp() RETURNS TRIGGER LANGUAGE plpgsql AS 'BEGIN NEW.timestamp = NOW(); RETURN NEW; END;'

  - changeSet:
      id: CREATE TRIGGER update_users_set_now_to_timestamp
      author: Konstantin Chvilyov
      changes:
        - sql:
            sql: CREATE TRIGGER update_users_set_now_to_timestamp BEFORE UPDATE ON users FOR EACH ROW EXECUTE PROCEDURE set_now_to_timestamp();

【讨论】:

以上是关于postgresql设置自动更新时间方法的主要内容,如果未能解决你的问题,请参考以下文章

春季启动中的postgresql错误

Postgresql 用户管理

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

有没有办法设置“过期”时间,之后在 PostgreSQL 中自动删除数据条目?

Postgresql 创建主键并设置自动递增的三种方法

使用 sqlalchemy 连接到本地 postgresql