文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  TIMESTAMP 和 DATETIME 的自动初始化和更新

13.2.5 TIMESTAMP 和 DATETIME 的自动初始化和更新

TIMESTAMPDATETIME 列可以自动初始化和更新为当前日期和时间(即当前时间戳)。

对于表中的任何 TIMESTAMPDATETIME 列,您都可以将当前时间戳指定为默认值、自动更新值或两者。

  • 对于插入的未指定列值的行,自动初始化的列将设置为当前时间戳。

  • 当行的任何其他列的值从其当前值更改时,自动更新的列会自动更新为当前时间戳。如果所有其他列都设置为其当前值,则自动更新的列保持不变。要防止自动更新的列在其他列更改时更新,请显式将其设置为其当前值。要更新自动更新的列,即使其他列没有更改,请显式将其设置为它应该具有的值(例如,将其设置为 CURRENT_TIMESTAMP)。

此外,如果 explicit_defaults_for_timestamp 系统变量已禁用,则可以通过将任何 TIMESTAMP(但不是 DATETIME)列分配为 NULL 值来将其初始化或更新为当前日期和时间,除非它已定义为具有 NULL 属性以允许 NULL 值。

要指定自动属性,请在列定义中使用 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP 子句。子句的顺序无关紧要。如果在列定义中都存在,则任何一个都可以先出现。CURRENT_TIMESTAMP 的任何同义词都与 CURRENT_TIMESTAMP 具有相同的含义。这些是 CURRENT_TIMESTAMP()NOW()LOCALTIMELOCALTIME()LOCALTIMESTAMPLOCALTIMESTAMP()

DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP 的使用特定于 TIMESTAMPDATETIMEDEFAULT 子句也可以用于指定常量(非自动)默认值(例如,DEFAULT 0DEFAULT '2000-01-01 00:00:00')。

注意

以下示例使用 DEFAULT 0,这是一个默认值,它可能会生成警告或错误,具体取决于是否启用了严格的 SQL 模式或 NO_ZERO_DATE SQL 模式。请注意,TRADITIONAL SQL 模式包括严格模式和 NO_ZERO_DATE。请参见 第 7.1.11 节,“服务器 SQL 模式”

TIMESTAMPDATETIME 列定义可以为默认值和自动更新值都指定当前时间戳,也可以为其中一个指定,也可以为两者都不指定。不同的列可以具有自动属性的不同组合。以下规则描述了可能性

  • 使用 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP,该列的默认值为当前时间戳,并且会自动更新为当前时间戳。

    CREATE TABLE t1 (
      ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );
  • 使用 DEFAULT 子句但不使用 ON UPDATE CURRENT_TIMESTAMP 子句,该列将具有给定的默认值,并且不会自动更新为当前时间戳。

    默认值取决于 DEFAULT 子句是否指定 CURRENT_TIMESTAMP 或常量值。使用 CURRENT_TIMESTAMP,默认值为当前时间戳。

    CREATE TABLE t1 (
      ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      dt DATETIME DEFAULT CURRENT_TIMESTAMP
    );

    使用常量,默认值为给定的值。在这种情况下,该列根本没有自动属性。

    CREATE TABLE t1 (
      ts TIMESTAMP DEFAULT 0,
      dt DATETIME DEFAULT 0
    );
  • 使用 ON UPDATE CURRENT_TIMESTAMP 子句和常量 DEFAULT 子句,该列会自动更新为当前时间戳,并具有给定的常量默认值。

    CREATE TABLE t1 (
      ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
      dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP
    );
  • 使用 ON UPDATE CURRENT_TIMESTAMP 子句但不使用 DEFAULT 子句,该列会自动更新为当前时间戳,但不会将当前时间戳作为其默认值。

    在这种情况下,默认值取决于类型。 TIMESTAMP 的默认值为 0,除非定义为具有 NULL 属性,在这种情况下,默认值为 NULL

    CREATE TABLE t1 (
      ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,     -- default 0
      ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL
    );

    DATETIME 的默认值为 NULL,除非定义为具有 NOT NULL 属性,在这种情况下,默认值为 0。

    CREATE TABLE t1 (
      dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP,         -- default NULL
      dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0
    );

TIMESTAMPDATETIME 列没有自动属性,除非它们被显式指定,但有一个例外:如果 explicit_defaults_for_timestamp 系统变量已禁用,则第一个 TIMESTAMP 列都具有 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP,即使两者都没有被显式包含。要抑制第一个 TIMESTAMP 列的自动属性,请使用以下策略之一

  • 启用 explicit_defaults_for_timestamp 系统变量。在这种情况下,指定自动初始化和更新的 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP 子句是可用的,但不会分配给任何 TIMESTAMP 列,除非在列定义中显式包含。

  • 或者,如果 explicit_defaults_for_timestamp 已禁用,请执行以下操作之一

    • 使用指定常量默认值的 DEFAULT 子句定义列。

    • 指定 NULL 属性。这也会导致该列允许 NULL 值,这意味着您不能通过将该列设置为 NULL 来分配当前时间戳。分配 NULL 会将该列设置为 NULL,而不是当前时间戳。要分配当前时间戳,请将该列设置为 CURRENT_TIMESTAMP 或其同义词,如 NOW()

考虑以下表定义

CREATE TABLE t1 (
  ts1 TIMESTAMP DEFAULT 0,
  ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t2 (
  ts1 TIMESTAMP NULL,
  ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t3 (
  ts1 TIMESTAMP NULL DEFAULT 0,
  ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                ON UPDATE CURRENT_TIMESTAMP);

这些表具有以下属性

  • 在每个表定义中,第一个 TIMESTAMP 列没有自动初始化或更新。

  • 这些表在 ts1 列如何处理 NULL 值方面有所不同。对于 t1ts1NOT NULL,并且为其分配 NULL 值会将其设置为当前时间戳。对于 t2t3ts1 允许 NULL,并且为其分配 NULL 值会将其设置为 NULL

  • t2t3ts1 的默认值方面有所不同。对于 t2ts1 被定义为允许 NULL,因此在没有显式 DEFAULT 子句的情况下,默认值也是 NULL。对于 t3ts1 允许 NULL,但具有 0 的显式默认值。

如果 TIMESTAMPDATETIME 列定义在任何地方包含一个显式的小数秒精度值,则必须在整个列定义中使用相同的数值。这是允许的

CREATE TABLE t1 (
  ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
);

这是不允许的

CREATE TABLE t1 (
  ts TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(3)
);

TIMESTAMP 初始化和 NULL 属性

如果 explicit_defaults_for_timestamp 系统变量被禁用,则默认情况下 TIMESTAMP 列为 NOT NULL,不能包含 NULL 值,并且分配 NULL 会分配当前时间戳。要允许 TIMESTAMP 列包含 NULL,请使用 NULL 属性显式声明它。在这种情况下,默认值也会变为 NULL,除非被指定了不同默认值的 DEFAULT 子句覆盖。可以使用 DEFAULT NULL 显式指定 NULL 作为默认值。(对于没有使用 NULL 属性声明的 TIMESTAMP 列,DEFAULT NULL 是无效的。)如果 TIMESTAMP 列允许 NULL 值,则分配 NULL 会将其设置为 NULL,而不是当前时间戳。

下表包含一些允许 NULL 值的 TIMESTAMP

CREATE TABLE t
(
  ts1 TIMESTAMP NULL DEFAULT NULL,
  ts2 TIMESTAMP NULL DEFAULT 0,
  ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
);

允许 NULL 值的 TIMESTAMP 列在插入时 不会 获取当前时间戳,除非满足以下条件之一

换句话说,如果 TIMESTAMP 列被定义为允许 NULL 值,则只有在它的定义包含 DEFAULT CURRENT_TIMESTAMP 时,它才会自动初始化

CREATE TABLE t (ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);

如果 TIMESTAMP 列允许 NULL 值,但它的定义不包含 DEFAULT CURRENT_TIMESTAMP,则您必须显式插入与当前日期和时间相对应的值。假设表 t1t2 具有以下定义

CREATE TABLE t1 (ts TIMESTAMP NULL DEFAULT '0000-00-00 00:00:00');
CREATE TABLE t2 (ts TIMESTAMP NULL DEFAULT NULL);

要将任一表中的 TIMESTAMP 列在插入时设置为当前时间戳,请显式分配该值。例如

INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);
INSERT INTO t1 VALUES (NOW());

如果 explicit_defaults_for_timestamp 系统变量被启用,则只有在使用 NULL 属性声明时,TIMESTAMP 列才允许 NULL 值。此外,无论使用 NULLNOT NULL 属性声明,TIMESTAMP 列都不允许分配 NULL 来分配当前时间戳。要分配当前时间戳,请将该列设置为 CURRENT_TIMESTAMP 或其同义词,如 NOW()