34

我观察到在 MySQL 时间戳列中插入/更新 NULL 的意外行为。

考虑以下陈述。

create table temp(id int, hireDate timestamp default 0);
insert into temp (id) values(1);
insert into temp (id, hireDate) values(2, null);
select * from temp;
id  hireDate
-----------------------------
1   
2   2012-09-19 10:54:10.0

第一次插入(当hiredateSQL 中未指定时,hireDatenull(0)是预期的。

但是,当在 SQL 中传递显式 null 时,会插入当前日期时间,这是意外的。为什么会这样?

注意:Hibernate 使用第二种类型的插入,因此它成为一个问题。如何将 null 插入时间戳列?

4

6 回答 6

33

http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html

此外,您可以将任何 TIMESTAMP 列初始化或更新为当前日期和时间,方法是为其分配 NULL 值,除非它已使用 NULL 属性定义以允许 NULL 值。

为了允许 TIMESTAMP 可以为空,请使用 NULL 属性创建它,或者更改表并添加 NULL 属性。在 create 语句中,它类似于。

CREATE TABLE t1 (tsvalue TIMESTAMP NULL, ... );

NULL值插入到具有 NULL 属性集的TIMESTAMP字段将导致该字段被设置为 NULL 而不是 NOW()。

于 2012-09-19T05:46:09.130 回答
11

您可以将 NULL 插入和更新到 MySQL 时间戳中。

创建表:

create table penguins(id int primary key auto_increment, the_time timestamp NULL);

插入一些行:

insert into penguins(the_time) values (now());
insert into penguins(the_time) values (null);
insert into penguins(the_time) values (0);
insert into penguins(the_time) values ('1999-10-10 01:02:03');

哪个打印:

select * from penguins

1   2015-01-23 15:40:36
2   
3   0000-00-00 00:00:00
4   1999-10-10 01:02:03

以数据类型调用的列the_timetimestamp在第二行的值为 NULL。

于 2015-01-23T20:37:53.440 回答
4

您需要更改hireDate 列的默认值。默认值应为空

create table temp(id int, hireDate timestamp default 0);

应该是这样的:

create table temp(id int, hireDate timestamp null);
于 2012-09-19T06:06:16.153 回答
0

如果要在hireDate表的列中插入 NULL,则必须提供 null

INSERT INTO temp (id, hireDate) VALUES(3, null);

因为Datatype 是,所以在创建列hireDatetimestamp时候应该定义为null

于 2012-09-19T05:44:19.050 回答
0

永远不要将任何应用程序值存储到 MySQL 时间戳类型列中。仅将时间戳类型用于数据库服务器端动态时间戳(请参阅 DEFAULT 和 ON UPDATE 列属性)。通过调用列“mysql_row_created_at”和“mysql_row_updated_at”来明确说明。

请注意,MySQL 将其时间戳类型物理存储为数字 UNIX-epoch-delta,因此它具有 UTC 的隐式时区,这使其不受会话(AKA 连接)级别的时区更改的影响。

远离“日期时间”类型,在存储任何具有已知时区的值时更是如此。'datetime' 类型很像一串压缩数字。没有存储时区详细信息。

“日期”类型通常可以使用。请注意,尽管在某些情况下,它将被解释为(活动时区的)午夜的日期时间,这将导致您应该避免的所有与“日期时间”相关的混淆。

对于任何应用程序端的日期时间值,使用“int unsigned”、“bigint”(有符号)、“double”(有符号)或小数(N,P)来简单地存储 UNIX-epoch-deltas . 如果不是秒,请确保在列名后缀中显示分辨率。

例子:

`mysql_row_created_at` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
`mysql_row_updated_at` TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

`epoch` int unsigned NOT NULL,
`epoch_ms` bigint NOT NULL,
`epoch_us` bigint NOT NULL,
`epoch` double NOT NULL,
`epoch6` decimal(16,6),

尽可能多地对待您的数据库作为哑存储。所以只能在应用程序端进行任何转换,而不是在数据库端。

很高兴知道:

SELECT @@GLOBAL.TIME_ZONE
, @@SESSION.TIME_ZONE
, @@SESSION.TIMESTAMP
, UNIX_TIMESTAMP(NOW(6))
;
于 2018-07-15T11:06:41.257 回答
0

从旧的 mysql 5.6.44-86.0 升级到 aurora mysql 5.7.12 时,我遇到了类似的行为。代码将 NULL 作为时间戳插入并期望写入全 0 日期 - 相反它抛出错误“列 'XXXX' 不能为空”。我通过将组参数explicit_defaults_for_timestamp 设置为0 解决了这个问题,然后允许将时间戳列插入/更新为null 而不会出错。

于 2021-09-21T14:47:20.740 回答