13.2.5 TIMESTAMP 和 DATETIME 的自动初始化和更新
TIMESTAMP 和 DATETIME 列可以自动初始化和更新到当前日期和时间(即当前时间戳)。
对于任何 TIMESTAMP 或 DATETIME 列在表中,您可以将当前时间戳分配为默认值、自动更新值或两者:
-
一个自动初始化的列将在插入行中设置为当前时间戳,如果插入行未指定该列的值。
-
一个自动更新的列将在任何其他列的值发生变化时自动更新到当前时间戳。一个自动更新的列将保持不变,如果所有其他列保持不变。要防止自动更新的列在其他列变化时更新,请明确地将其设置为当前值。要在其他列不变化时更新自动更新的列,请明确地将其设置为所需的值(例如,将其设置为
CURRENT_TIMESTAMP)。
此外,如果禁用 explicit_defaults_for_timestamp 系统变量,您可以将任何 TIMESTAMP (但不是 DATETIME) 列初始化或更新到当前日期和时间,通过将其分配为 NULL 值,除非该列已定义为允许 NULL 值。
要指定自动属性,请使用 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP take in 列定义中。这些子句的顺序无关紧要。如果在列定义中同时出现这两个子句,可以出现的顺序无关紧要。任何 CURRENT_TIMESTAMP 的同义词都具有相同的含义,这些同义词是 CURRENT_TIMESTAMP、NOW()、LOCALTIME、LOCALTIME()、LOCALTIMESTAMP 和 LOCALTIMESTAMP()。
使用 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 是专门为TIMESTAMP 和DATETIME 设计的。 DEFAULT take also can be used to specify a constant (nonautomatic) default value (for example, DEFAULT 0 or DEFAULT '2000-01-01 00:00:00').
以下示例使用 DEFAULT 0,一个可以根据是否启用严格 SQL 模式或 NO_ZERO_DATE SQL 模式产生警告或错误的默认值。注意 TRADITIONAL SQL 模式包括严格模式和 NO_ZERO_DATE。请参阅第7.1.11节,“服务器 SQL 模式”。
TIMESTAMP 或DATETIME 列定义可以指定当前时间戳为默认值和自动更新值,但只为一个或都为另一个或都为都没有。不同的列可以具有不同的自动属性组合。以下规则描述了可能的组合:
-
同时使用
DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP,该列具有当前时间戳为其默认值,并且自动更新到当前时间戳。CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -
使用
DEFAULTtake 但没有ON UPDATE CURRENT_TIMESTAMPtake,该列具有给定的默认值,但不自动更新到当前时间戳。默认值取决于
DEFAULTtake 是否指定CURRENT_TIMESTAMP或常量值。使用CURRENT_TIMESTAMP,默认值为当前时间戳。CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP );使用常量,default 是给定的值。在这种情况下,该列没有自动属性。
CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0, dt DATETIME DEFAULT 0 ); -
使用
ON UPDATE CURRENT_TIMESTAMPtake 和常量DEFAULTtake,该列自动更新到当前时间戳,并具有给定的常量默认值。CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP ); -
使用
ON UPDATE CURRENT_TIMESTAMPtake 但没有DEFAULTtake,该列自动更新到当前时间戳,但不具有当前时间戳为其默认值。在这种情况下,default 取决于类型。
TIMESTAMP的默认值为 0,除非定义了NULL属性,在这种情况下,default 是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属性,在这种情况下,default 是 0。CREATE TABLE t1 ( dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP, -- default NULL dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0 );
TIMESTAMP 和 DATETIME 列没有自动属性,除非明确指定,以下是例外情况:如果 explicit_defaults_for_timestamp 系统变量被禁用,第一个 TIMESTAMP 列同时具有 DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP,除非明确指定。要抑制第一个 TIMESTAMP 列的自动属性,可以使用以下策略:
-
启用
explicit_defaults_for_timestamp系统变量。在这种情况下,DEFAULT CURRENT_TIMESTAMP和ON 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值。对于t1,ts1是NOT NULL,将其设置为NULL将设置为当前时间戳。对于t2和t3,ts1允许NULL,将其设置为NULL将设置为NULL。 -
t2和t3在ts1的默认值上有所不同。对于t2,ts1允许NULL,因此在缺省情况下,ts1的默认值也为NULL,除非使用DEFAULT子句。对于t3,ts1允许NULL,但其默认值为 0。
如果 TIMESTAMP 或 DATETIME 列定义包含明确的分秒精度值-anywhere,该值必须在整个列定义中保持一致。这是允许的:
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)
);
如果 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 值的 TIMESTAMP 列:
CREATE TABLE t
(
ts1 TIMESTAMP NULL DEFAULT NULL,
ts2 TIMESTAMP NULL DEFAULT 0,
ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
);
一个允许 NULL 值的 TIMESTAMP 列不会在插入时取当前时间戳,除非满足以下条件之一:
-
其缺省值被定义为
CURRENT_TIMESTAMP,并且没有为该列指定值 -
CURRENT_TIMESTAMP或其同义词,如NOW()被明确插入到列中
换言之,一个TIMESTAMP列,如果定义允许NULL值,自动初始化,只要定义包括DEFAULT CURRENT_TIMESTAMP:
CREATE TABLE t (ts TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP);
如果TIMESTAMP列允许NULL值,但定义不包括DEFAULT CURRENT_TIMESTAMP,您必须明确地插入当前日期和时间对应的值。假设表t1和t2具有以下定义:
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值,只要声明了NULL属性。同时,TIMESTAMP列不允许将当前时间戳分配给NULL,无论声明了NULL或NOT NULL属性。要分配当前时间戳,设置列为CURRENT_TIMESTAMP或同义词,如NOW()。