MySQL MySQL如何处理数字表达式评估过程中的溢出?
在进行数字计算的过程中,可能会出现数字溢出的情况。MySQL针对这种情况,采取了不同的处理方式。
阅读更多:MySQL 教程
MySQL的数字类型
在探究MySQL如何处理数字溢出之前,我们先来了解一下MySQL中的数字类型。
MySQL中的数字类型主要有以下几种:
- TINYINT
- SMALLINT
- MEDIUMINT
- INT
- BIGINT
- FLOAT
- DOUBLE
这几种类型所占用的存储空间以及表示范围如下:
类型 | 存储空间 | 范围 |
---|---|---|
TINYINT | 1 字节 | -128 到 127(有符号),0 到 255(无符号) |
SMALLINT | 2 字节 | -32,768 到 32,767(有符号),0 到 65,535(无符号) |
MEDIUMINT | 3 字节 | -8,388,608 到 8,388,607(有符号),0 到 16,777,215(无符号) |
INT | 4 字节 | -2,147,483,648 到 2,147,483,647(有符号),0 到 4,294,967,295(无符号) |
BIGINT | 8 字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807(有符号),0 到 18,446,744,073,709,551,615(无符号) |
FLOAT | 4 字节 | 大约 -3.40282347E+38 到 -1.17549435E-38、0 和 1.17549435E-38 到 3.40282347E+38 |
DOUBLE | 8 字节 | 大约 -1.7976931348623157E+308 到 -2.2250738585072014E-308、0 和 2.2250738585072014E-308 到 1.7976931348623157E+308 |
这些类型在MySQL中都有其独特的应用场景。
数字溢出导致的问题
当进行数字运算时,如果计算结果超出了该数据类型所能表示的范围,就会发生数字溢出。
例如,当使用tinyint类型为a和b赋值,然后使用a + b运算时,如果结果超出了tinyint类型的范围,就会发生数字溢出,结果将是不正确的。
DECLARE a TINYINT;
DECLARE b TINYINT;
SET a = 127;
SET b = 1;
SELECT a + b;
在上面的例子中,a的值为127,b的值为1,它们的和已经超出了tinyint类型能够表示的范围。在MySQL中,数字溢出的结果是未定义的,执行上述SELECT语句将会返回-128。
MySQL的数字运算
MySQL有着相对复杂的数字运算规则。
对于数字类型为Unsigned的列,MySQL遵循以下规则:
- 如果将一个负数插入unsigned列中,其值会被解释为无符号整数,即该值会加上2^n,其中n是数值类型的位数。例如,当一个有符号的tinyint类型的列包含值-1时,它在该列被定义为无符号类型时,将变成255。
对于数字类型为Signed的列,MySQL遵循以下规则:
- 当两个数进行加、减、乘或一元减除操作时,MySQL会根据它们的精度和大小来选择正确的结果类型(容量越大的类型,其表示的数字范围越大)。
- 在除法运算中,如果除数为0,则MySQL将返回NULL。如果被除数为0,则MySQL将返回0或NULL,取决于所使用的SQL_MODE。
- 对于整数类型的数值列,如果除法结果需要小数部分,则将其转换为浮点类型来存储结果,此时将使用float或double类型,具体取决于数值列的定义和MySQL版本。
MySQL处理数字溢出的方式
在数字计算中,MySQL的处理方式取决于具体的数值类型:
- 对于整型类型,如果计算结果的绝对值或者大小超出了该类型所能表示的范围,MySQL会截断最高位的位数,将结果保留在该类型的范围内,并发出一个警告。
- 对于浮点型类型,如果计算结果超出了类型范围,则会返回对应的有限取值:正无穷、负无穷或NaN。
为了方便演示,下面我们将从以下两个方面来说明MySQL的数字溢出处理方式:
- 整型类型溢出;
- 浮点型类型溢出。
整型类型溢出
首先,我们来看一个整型类型溢出的例子:
DECLARE a BIGINT;
DECLARE b BIGINT;
SET a = 9223372036854775807;
SET b = 1;
SELECT a + b;
在上面的例子中,a的值为9223372036854775807,b的值为1,它们的和超出了bigint类型能够表示的范围。
在这种情况下,MySQL会截断最高位的位数,将结果保留在bigint类型的范围内,并返回一个警告。执行上述SELECT语句,将输出以下结果和警告:
+-----------------------+
| a + b |
+-----------------------+
| 9223372036854775808 |
+-----------------------+
1 row in set, 1 warning (0.00 sec)
Warning (Code 1292): Truncated incorrect BIGINT value: '9223372036854775808'
从结果和警告中,我们可以看到MySQL将计算结果截断后保留在bigint类型的范围内,同时发出了一个警告。
浮点型类型溢出
然后,我们再来看一个浮点型类型溢出的例子:
DECLARE a FLOAT;
DECLARE b FLOAT;
SET a = 1e+307;
SET b = 1;
SELECT a * b;
在上面的例子中,a的值为1e+307,b的值为1,它们的乘积超出了float类型能够表示的范围。
在这种情况下,MySQL会返回对应的有限取值:正无穷、负无穷或NaN。执行上述SELECT语句,将输出以下结果:
+----------------------------------------------------------------+
| a * b |
+----------------------------------------------------------------+
| INF |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
从结果中,我们可以看到MySQL返回了一个正无穷的值。
结论
MySQL有着相对复杂的数字运算规则,并且在数字计算过程中可能会出现数字溢出的情况。针对这种情况,MySQL采取了不同的处理方式。对于整型类型,如果计算结果超出了类型范围,将会截断最高位的位数,将结果保留在该类型的范围内,并发出一个警告;对于浮点型类型,如果计算结果超出了类型范围,将会返回对应的有限取值:正无穷、负无穷或NaN。在编写MySQL应用程序时,需要注意数字溢出可能导致的问题,并根据实际情况选择适合的数据类型。