UPDATE sq_question_content as c
INNER JOIN sq_question as s ON c.question_id = s.id
SET
c.create_at = FROM_UNIXTIME(s.pubdate) ,
c.update_at = FROM_UNIXTIME(s.pubdate);

这个错误的核心原因是:sq_question.pubdate 并非 MySQL 原生的 TIMESTAMP 类型,而是以整数(Unix 时间戳,秒数)形式存储的数值(如 1459849198 是 2016年4月5日的 Unix 时间戳),直接用 CAST(...) AS DATETIME 无法将数字转为合法的 datetime 格式,因此触发 1292 错误。

解决方案:使用 FROM_UNIXTIME() 函数转换 Unix 时间戳

MySQL 提供了 FROM_UNIXTIME(unix_timestamp) 函数,可将秒级 Unix 时间戳直接转换为 DATETIME 类型,替换原来的 CAST 即可解决问题:

UPDATE `sq_question_content` AS c
INNER JOIN sq_question AS s ON c.question_id = s.id
SET 
    c.create_at = FROM_UNIXTIME(s.pubdate),
    c.update_at = FROM_UNIXTIME(s.pubdate);

额外说明与验证步骤

1. 先验证时间戳转换结果(避免误操作)

执行更新前,先通过 SELECT 确认转换后的时间是否正确:

SELECT 
    s.id,
    s.pubdate AS unix_timestamp, -- 原始Unix时间戳
    FROM_UNIXTIME(s.pubdate) AS converted_datetime -- 转换后的datetime
FROM sq_question AS s
LIMIT 10; -- 查看前10条数据的转换结果

2. 处理毫秒级 Unix 时间戳(若存在)

如果 pubdate13位的毫秒级时间戳(如 1459849198123),直接用 FROM_UNIXTIME() 会得到错误时间,需先除以1000:

UPDATE `sq_question_content` AS c
INNER JOIN sq_question AS s ON c.question_id = s.id
SET 
    c.create_at = FROM_UNIXTIME(s.pubdate / 1000),
    c.update_at = FROM_UNIXTIME(s.pubdate / 1000);

3. 过滤无效时间戳(可选)

若存在非法的时间戳值(如0、负数、超出datetime范围的数值),可通过 WHERE 条件过滤,避免再次报错:

UPDATE `sq_question_content` AS c
INNER JOIN sq_question AS s ON c.question_id = s.id
SET 
    c.create_at = FROM_UNIXTIME(s.pubdate),
    c.update_at = FROM_UNIXTIME(s.pubdate)
WHERE 
    s.pubdate > 0 -- 排除0或负数
    AND s.pubdate < FROM_UNIXTIME('2038-01-19 03:14:07') -- 排除超出Unix时间戳上限的值
    AND FROM_UNIXTIME(s.pubdate) IS NOT NULL; -- 确保转换结果有效

4. 确认目标字段类型

确保 sq_question_content.create_atupdate_atDATETIME/DATETIME(6) 类型,若为其他类型(如 VARCHAR),需先修改字段类型:

ALTER TABLE sq_question_content
MODIFY COLUMN create_at DATETIME NOT NULL,
MODIFY COLUMN update_at DATETIME NOT NULL;

Leave A Comment

Recommended Posts