首页 > 解决方案 > MySQL 未按预期执行 CURRENT_TIMESTAMP 更新

问题描述

经过大量研究和这里提出的几个类似问题,我得出了一些结论,但与往常一样,还有更多问题。

这涉及到explicit_defaults_for_timestamp

假设explicit_defaults_for_timestamp已关闭,这将起作用:

架构:

CREATE TABLE IF NOT EXISTS `updated_tables` (
  `table_name` VARCHAR(50) NOT NULL,
  `updated_at` TIMESTAMP(6)  NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  PRIMARY KEY (`table_name`),
  UNIQUE INDEX `table_name_UNIQUE` (`table_name` ASC))
  ENGINE = InnoDB;

和查询:

INSERT INTO `updated_tables` (`table_name`,`updated_at`) VALUES ('products',NULL) ON DUPLICATE KEY UPDATE `table_name`=VALUES(`table_name`), `updated_at`=VALUES(`updated_at`);

第一次发送查询时,表中会填充“产品”和当前时间戳。如果我重复查询,则更新字段“updated_at”。根据定义,当我发送 NULL 值时,即使不允许,MySQL 也会更新该列。一切都很好,并且按预期工作。

假设我打开了explicit_defaults_for_timestamp 如果我使用上面的查询,它会抱怨NULL is not allowed,这符合规则。

问题是,如何在打开explicit_defaults_for_timestamp的情况下拥有相同的功能?有一种解决方案可以引入额外的列(varchar),例如以毫秒为单位的时间戳。当我更新它时,MySQL 会相应地更新 updated_at 。但这看起来有点矫枉过正,我还不如手动更新 updated_at 。我想把这个责任转移到 MySQL 级别,而不是以编程方式进行。

简而言之,如何对 table_name 执行更新,并正确设置 updated_at。这里的诀窍是我有很多更新(缓存表),但实际上根本没有更改 table_name 值。

可能吗?或者我必须关闭explicit_defaults_for_timestamp?

关闭它是一个错误的决定吗?看看这个AWS RDS帖子似乎没问题,但我不确定。

附带问题:

如果我决定自己执行更新,构建它的方法是什么?目前 MySQL CURRENT_TIMESTAMP(6) 具有以下构造: 2018-07-10 11:32:43.490100 如何使用 Javascript 创建相同的构造?我想到的第一件事是获取当前日期,并将当前时间戳的最后 6 位附加到它上面。

标签: mysql

解决方案


您可以在 INSERT 上创建触发器并始终updated_at使用 CURRENT_TIMESTAMP 设置值 - 最干净的方法,但这可能会减慢您的更新速度。以编程方式设置列值将比触发触发器更快。

如果您从 Node.js 执行查询,那么您可以使用new Date().getTime()以毫秒为单位获取 Unix 时间戳,然后像这样构造您的查询

UPDATE tbl SET col_1 = val_1, col_2 = val_2, updated_at = FROM_UNIXTIME(js_milliseconds / 1000) 
WHERE id = desired_id

推荐阅读