当我和你一起,并且愚蠢的几乎没有经验时,我决定用PHP生成时间戳并将它们存储在我的MySQL innodb表的INT
列中是个好主意。现在,当此表具有数百万条记录并需要一些基于日期的查询时,是时候将此列转换为TIMESTAMP
。我该怎么做?
Currenlty,我的桌子看起来像这样:
id (INT) | message (TEXT) | date_sent (INT)
---------------------------------------------
1 | hello? | 1328287526
2 | how are you? | 1328287456
3 | shut up | 1328234234
4 | ok | 1328678978
5 | are you... | 1328345324
以下是我提出的查询,将date_sent
列转换为TIMESTAMP
:
-- creating new column of TIMESTAMP type
ALTER TABLE `pm`
ADD COLUMN `date_sent2` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP();
-- assigning value from old INT column to it, in hope that it will be recognized as timestamp
UPDATE `pm` SET `date_sent2` = `date_sent`;
-- dropping the old INT column
ALTER TABLE `pm` DROP COLUMN `date_sent`;
-- changing the name of the column
ALTER TABLE `pm` CHANGE `date_sent2` `date_sent` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP();
对我来说一切似乎都是正确的,但是当UPDATE
pm SET
date_sent2 =
date_sent ;
到来时,我收到警告并且时间戳值仍为空:< / p>
+---------+------+--------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------+
| Warning | 1265 | Data truncated for column 'date_sent2' at row 1 |
我做错了什么,是否有办法解决这个问题?
答案 0 :(得分:34)
你快到了,使用FROM_UNIXTIME()
而不是直接复制价值。
-- creating new column of TIMESTAMP type
ALTER TABLE `pm`
ADD COLUMN `date_sent2` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP();
-- Use FROM_UNIXTIME() to convert from the INT timestamp to a proper datetime type
-- assigning value from old INT column to it, in hope that it will be recognized as timestamp
UPDATE `pm` SET `date_sent2` = FROM_UNIXTIME(`date_sent`);
-- dropping the old INT column
ALTER TABLE `pm` DROP COLUMN `date_sent`;
-- changing the name of the column
ALTER TABLE `pm` CHANGE `date_sent2` `date_sent` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP();
答案 1 :(得分:1)
这种方式不需要临时字段来存储时间戳类型的值,因此在更改大型表时应该更加停机友好,并且它也适用于 DATE(TIME) 类型字段(见下文)。
将时间戳或日期时间转换为 int 请参见:Mysql: Convert column from timestamp to int and perform conversion for each update
首先,我们必须将时间戳类型转换为没有标点符号的数字日期时间(如 202102060020302),因为数字完整形式对于 int 存储来说太长,应该将字段更改为 bigint 类型(如果您需要 datetime 类型,这将是 TEXT 类型) :
ALTER TABLE `table` CHANGE `field` `field` BIGINT NOT NULL;
然后将时间戳转换为数字日期时间(如果您需要日期时间类型,则应删除 CAST()):
UPDATE `table` SET `field` = CAST(FROM_UNIXTIME(`field`) AS UNSIGNED);
最后,我们可以将字段类型更改为时间戳,而 mysql 将完成转换数字日期时间的其余工作(如果您需要日期时间类型,只需使用 DATETIME):
ALTER TABLE `table` CHANGE `field` `field` TIMESTAMP NOT NULL;
参考https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-conversion.html
> mysql> SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0;
> +-----------+-------------+--------------+
> | CURTIME() | CURTIME()+0 | CURTIME(3)+0 |
> +-----------+-------------+--------------+
> | 09:28:00 | 92800 | 92800.887 |
> +-----------+-------------+--------------+
> mysql> SELECT NOW(), NOW()+0, NOW(3)+0;
> +---------------------+----------------+--------------------+
> | NOW() | NOW()+0 | NOW(3)+0 |
> +---------------------+----------------+--------------------+
> | 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 |
> +---------------------+----------------+--------------------+