我的故事从一个问题开始,当时我发现了新的错误:
[22001][1690] 数据截断:BIGINT UNSIGNED 值超出 '(`cur`.`count_rows` - `perv`.`count_rows`)' 的范围
嗯,我明白发生了什么,我的差异小于零,但是需要做什么呢?
我有大约下表:
CREATE TABLE daily_count_rows (
created_day DATE NOT NULL PRIMARY KEY,
count_rows BIGINT UNSIGNED NOT NULL
);
以及下面抛出“值超出范围”错误的查询
SELECT cur.created_day - prev.created_day
FROM daily_count_rows cur
INNER JOIN daily_count_rows prev ON prev.id= cur.table_schema
AND perv.created_day = CURDATE() - INTERVAL 1 DAY
WHERE cur.created_day = CURDATE()
第一个动作,像任何其他程序员一样,试图在 StackOverflow 上找到这个问题,我找到了解决方案,在查询前添加 sql_mode:
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
SELECT ts.count_rows - ts2.count_rows AS rows_diff
-- ...
但是如果您无权更改 SQL_MODE 怎么办?
我们有什么问题?
第一个变量 ts.count_rows 是 BIGINT UNSIGNED 类型,如果您尝试计算和或差,计算的变量将是相同类型。
因此,让我们尝试使用 CAST 将类型转换为所需的类型
SELECT CAST(ts.count_rows - ts2.count_rows AS SIGNED) AS rows_diff
我想你猜到这会抛出同样的错误,因为 MySQL 会进行计算,然后转换为有符号类型。
最后,我通过以下方式解决了这个问题:
SELECT IF(cur.created_day > prev.created_day,
cur.created_day - prev.created_day,
CAST(cur.created_day - prev.created_day as SIGNED) * -1
)
FROM daily_count_rows cur
INNER JOIN daily_count_rows prev ON prev.id= cur.table_schema
AND perv.created_day = CURDATE() - INTERVAL 1 DAY
WHERE cur.created_day = CURDATE();
如果您知道解决此问题的另一种方法,请与我分享。
谢谢!