Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Automatic Initialization and Updating for TIMESTAMP and DATETIME

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

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

对于任何 TIMESTAMPDATETIME 列,可以将当前时间戳作为默认值、自动更新值或两者。

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

  • 自动更新的列将在其他列的值更改时自动更新到当前时间戳。如果其他列保持不变,自动更新的列将保持不变。要防止自动更新的列在其他列更改时更新,请明确设置其当前值。要在其他列不变时更新自动更新的列,请明确设置其应有的值(例如,设置为 CURRENT_TIMESTAMP)。

此外,如果 explicit_defaults_for_timestamp 系统变量被禁用,可以通过将其设置为 NULL 值来初始化或更新任何 TIMESTAMP(但不是 DATETIME)列,除非它被定义为允许 NULL 值。

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

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

Note

以下示例使用 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 列没有自动初始化或更新。

  • 这些表在处理 NULL 值方面有所不同。t1 中的 ts1 列不是 NULL,将其设置为 NULL 将其设置为当前时间戳。t2t3 中的 ts1 列允许 NULL,将其设置为 NULL 将其设置为 NULL

  • t2t3 在默认值方面对 ts1 有所不同。对于 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 列在插入时不会自动获取当前时间戳,除非满足以下条件:

换言之,允许 NULL 值的 TIMESTAMP 列只有在其定义中包含 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系统变量,TIMESTAMP列仅允许在声明了NULL属性时具有空值。此外,TIMESTAMP列不允许将空值分配给当前时间戳,无论是否声明了NULLNOT NULL属性。要分配当前时间戳,请将列设置为CURRENT_TIMESTAMP或同义词,如NOW()