MySQL版本:5.5.38-0ubuntu0.14.04.1
表格结构:
CREATE TABLE `route_points2` (
`dist` tinyint(4) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
数据:1行,dist
等于200
SQL:
SELECT * FROM route_points2 WHERE -1*dist < 1;
错误:
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(<cache>(-(1)) * `db_name`.`route_points2`.`dist`)'
为什么mysql会将-1*dist
转换为BIGINT UNSIGNED
?
上述错误可以通过将dist
转换为SIGNED
来解决:
SELECT * FROM route_points2 WHERE -1*CAST(dist AS SIGNED) < 1;
这很好用。
但我不明白为什么mysql为BIGINT UNSIGNED
-1*dist
答案 0 :(得分:0)
由于您使用的是UNSIGNED编号,并且与SIGNED编号(-1)进行比较,因此mysql需要将您的UNSIGNED转换为SIGNED。我猜它选择BIGINT能够应对所有可能的INT。
使用MySQL 5.5改变了行为,请查看此http://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html
要使其工作,请将表定义为:
CREATE TABLE `route_points2` (
`dist` tinyint NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
或者如果您需要值&gt; 127使用:
CREATE TABLE `route_points2` (
`dist` smallint NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
答案 1 :(得分:0)
默认情况下,MySQL不再(不再)通过减去无符号操作数产生带符号结果,也不会产生混合符号乘法。
您必须启用the MySQL mode MODE_NO_UNSIGNED_SUBTRACTION才能恢复减法的旧(非常合理)默认行为。似乎没有用于乘法的并行促销模式。
正如您已经发布的那样,解决方案是在减法的两个操作数上使用CAST运算符,并在可能混合的乘法中使用任何无符号操作数。
除此之外:类型的宽度无关紧要。在我第一次遇到我认为它只会影响BIGINT操作数。因为没有更宽的签名类型,并且大值无法正确表示,在这种情况下我会理解错误条件,但正如您所看到的,此错误一直发生到最小的整数类型(例如从TINYINT UNSIGNED列中拉出的值。)