BIGINT UNSIGNED 值超出范围。

46

我遇到了错误

'(1301980250 - mydb.news_articles.date)'中BIGINT UNSIGNED值超出范围。

当我运行这个查询时

SELECT *, ((1 / log(1301980250 - date)) * 175) as weight FROM news_articles ORDER BY weight;

如果移除ORDER BY条件,错误也会消失。该如何修复它?

更新: 日期字段包含Unix时间戳(例如:1298944082)。在将MySQL从5.0.x升级到5.5.x之后,出现了这个错误。

请问有什么帮助吗?


给我们一个日期保存的数据示例,我怀疑它与此有关。 - Khez
1
我猜Khez是对的,问题在于某个日期值大于1301980250。 - Brian Hooper
我仍然怀疑它会导致那个特定的错误,但这仍然是开始复制错误的一个起点。 - Khez
很抱歉,我没有完全复制代码。查询中有一个按权重排序的 ORDER BY(我已更新原帖)。只有当它存在时才会出现错误。 - Joyce Babu
哦,它也有限制吗?你能给我们表定义吗?执行SHOW CREATE TABLE news_articles。 - Khez
7个回答

87

我最近遇到了这个问题,并发现最合理的解决方案是将任何无符号整数转换为有符号整数。

 SELECT *, ((1 / log(1301980250 - cast(date as signed)) * 175) as weight FROM news_articles ORDER BY weight

真奇怪!log()函数不能对负数求值! - Jasen
@Jasen:确实,对于负数来说,对数是没有定义的数学定理。证明如下:对数是“10的幂”的反函数,但所有的10的幂都是严格正数,这是幂的定义。因此不存在任何实数R使得10^(R) <= 0。 - Fabien Haddadi
工作了,谢谢,我不知道在有减法时必须使用CAST(my_var AS SIGNED) - Sergio Perez

17

根据wallyk的建议,该问题是由无符号整数溢出引起的。 可以通过以下方式解决:

  1. 使用SELECT *,((1 / log((date - 1301980250)* -1))* 175) as weight FROM news_articles ORDER BY weight; (对我有效)`
  2. 更改my.cnf中的sql_mode参数为NO_UNSIGNED_SUBTRACTION(尚未检查)

14
@wallyk - 回答自己的问题不会给我任何分数,所以我没有为了提高我的声誉而这样做。我在MySQL IRC上找到了答案。我很感激你的时间和努力,并且已经投票支持了你的回答。但是你没有提供解决问题的方法,我想在这里分享它。 - Joyce Babu
6
如果您无法或不想修改配置文件,您也可以使用以下语句:SET sql_mode='NO_UNSIGNED_SUBTRACTION'; - Jérôme
1
@wallyk和其他正在阅读此内容的人 - 这简直是不正确的。您可以在提问时回答自己的问题。Stackoverflow希望有良好记录的答案和问题,提供答案的人并不重要。 - Luke
"NO_UNSIGNED_SUBTRACTION" 对我并没有解决问题。 - Erel Segal-Halevi

8

这有时可能是由于数据中存在空值造成的。

使用IFNULL来设置默认值(对于时间戳来说,0可能是一个不好的默认值,在这种情况下,最好是在WHERE子句中排除空日期)

SELECT (123456 - IFNULL(date, 0)) AS leVar


在我的情况下,我正在对一个无符号整数列中的0值执行value = value-1000操作。 - Vael Victus

4

没有人提到log()函数只对严格正数参数定义。使用log()时要注意减法操作。

至于原始问题,解决的关键因素是告诉我们日期列的数据类型。如果它是UNSIGNED的,MySQL可能不喜欢它。

规则是MySQL算术运算算法很差,当A编码的字节数比B少且B>A时,无法计算出如何从另一个A中减去操作数B(即执行A-B)。

例如:A = 12,为SMALLINT,B = 13 AS INT,则MySQL无法计算出A-B是多少(-1!)

要使MySQL内容满意,只需扩展操作数A的编码长度。如何?使用CAST(),或将A乘以小数。

可以看出,这不是溢出的问题,而是MySQL在处理算术符号方面的问题。微处理器,或更好的是人类,都可以执行此类算术运算...

使用CAST()是一种方法,或者简单地通过将操作数A乘以1(或1.0)来引发隐式转换:

例如:

1.*A - B

4

如果日期值在2011-04-04 22:10:50 PDT (2011-04-05 05:10:50 UTC)之后,将会导致该错误的出现,因为这会使表达式变为负数。


3

也许你可以使用 cast

SELECT *, ((1 / log(1301980250 - 将日期转换为有符号整数的 cast)) * 175) as weight FROM news_articles ORDER BY weight;


1

我刚刚在更新一个字段时遇到了这个问题,结果变成了小于0。

解决方案:请确认您的更新不会导致无符号字段的结果小于0。


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