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 );
-
使用
DEFAULT
take 但没有ON UPDATE CURRENT_TIMESTAMP
take,该列具有给定的默认值,但不自动更新到当前时间戳。默认值取决于
DEFAULT
take 是否指定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_TIMESTAMP
take 和常量DEFAULT
take,该列自动更新到当前时间戳,并具有给定的常量默认值。CREATE TABLE t1 ( ts TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP );
-
使用
ON UPDATE CURRENT_TIMESTAMP
take 但没有DEFAULT
take,该列自动更新到当前时间戳,但不具有当前时间戳为其默认值。在这种情况下,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()
。