毫秒级时间戳:如何在MySQL中保存它们

112

我需要使用MySQL开发一个应用程序,需要保存像"1412792828893"这样的值,它表示毫秒级别的时间戳。也就是自1970年1月1日以来的毫秒数。我将该行声明为timestamp,但不幸的是,这并没有起作用。所有值均设置为0000-00-00 00:00:00

CREATE TABLE IF NOT EXISTS `probability` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`segment_id` int(11) NOT NULL,
`probability` float NOT NULL,
`measured_at` timestamp NOT NULL,
`provider_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ;

如何声明才能保存具有此精度的时间戳值?


MySQL的哪个版本? - Strawberry
mysql Ver 14.14 分布式 5.6.11,适用于 Win32 (x86) - Luixv
看起来你很幸运。 - Strawberry
你手头上有以毫秒为单位的数值吗?如果是这样,为什么不直接存储为BIGINT呢? - Sandman
4个回答

180

您需要使用MySQL版本5.6.4或更高版本才能声明带有分数秒时间数据类型的列。不确定您是否拥有正确的版本?尝试运行SELECT NOW(3)。如果出现错误,则表示您没有正确的版本。

例如,DATETIME(3)将为您的时间戳提供毫秒分辨率,而TIMESTAMP(6)将在*nix风格的时间戳上为您提供微秒分辨率。

请阅读此文档:https://dev.mysql.com/doc/refman/8.0/en/fractional-seconds.html

NOW(3)将从您的MySQL服务器操作系统中以毫秒精度给出当前时间。

如果您有自Unix纪元以来的毫秒数,请尝试使用以下内容获取DATETIME(3)值

FROM_UNIXTIME(ms * 0.001)

JavaScript timestamps,例如,以自Unix纪元起的毫秒表示。

(请注意,MySQL内部的小数运算,如* 0.001,始终被处理为IEEE754双精度浮点数,因此在太阳变成白矮星之前失去精度的可能性很小。)

如果您正在使用较旧的MySQL版本并且需要亚秒级时间精度,则最好升级。其他任何方法都会迫使您进行混乱的解决方案。

如果由于某种原因无法升级,则可以考虑使用BIGINTDOUBLE列将JavaScript时间戳存储为数字。 FROM_UNIXTIME(col * 0.001)仍然可以正常工作。如果您需要当前时间以存储在这样的列中,则可以使用UNIX_TIMESTAMP() * 1000


我已将定义更改为timestamp(6),但是在使用以下语法添加值时INSERT INTO probability (measured_at, probability, provider_id, segment_id) VALUES( 1412877161519,0.7418073347680607,1,211623); 我仍然在“measured_at”列中得到0000-00-00 00:00:00.00000。我应该如何向此表插入值? - Luixv
1
@Luixv,您需要在输入时将值进行转换:INSERT ... VALUES(FROM_UNIXTIME(0.001 * 1412877161519), 0.7418 ... ); - Michael - sqlbot
1
乘以0.001是一个救命稻草!我从来没有想到它可以在不丢失小数秒的情况下工作。谢谢。 - Pavel S.
在我的情况下,由于我正在使用树莓派进行测试(在RPI上安装mysql 5.6非常麻烦),因此我选择将信息保存为Unix时间。 - silgon
已解决,乘以*0.001。 - user7436601

2
CREATE TABLE fractest( c1 TIME(3), c2 DATETIME(3), c3 TIMESTAMP(3) );

INSERT INTO fractest VALUES
('17:51:04.777', '2018-09-08 17:51:04.777', '2018-09-08 17:51:04.777');

2
请按照以下方式创建表格,通过指定时间戳的长度(长度可以是毫秒级的任意数字),例如timestamp(2)timestamp(3)timestamp(5)。Mysql版本应为5.6或以上。 https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
CREATE TABLE IF NOT EXISTS `probability` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`measured_at` timestamp(2) NOT NULL,
 PRIMARY KEY (`id`)
) ;

然后通过Java将时间戳传递。

statement.setTimestamp(2, new Timestamp(new Date().getTime()))

0
您可以按如下方式使用BIGINT:
CREATE TABLE user_reg (
user_id INT NOT NULL AUTO_INCREMENT,
identifier INT,
phone_number CHAR(11) NOT NULL,
verified TINYINT UNSIGNED NOT NULL,
reg_time BIGINT,
last_active_time BIGINT,
PRIMARY KEY (user_id),
INDEX (phone_number, user_id, identifier)
   );

BIGINT是8个字节,不过有没有更有效率的选择呢?这相当于每个记录比你需要的多两个字节。 - S. Imp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接