12.22.3 table 达式处理
对于精确 math,将尽可能使用给定的精确值数字。例如,比较中的数字将完全按照给定的方式使用,而不会更改值。在严格的 SQL 模式下,对于INSERT进入具有精确数据类型(DECIMAL或整数)的列,如果数字在列范围内,则会插入一个带有其精确值的数字。检索时,该值应与插入的值相同。 (如果未启用严格的 SQL 模式,则INSERT的截断是允许的。)
数值 table 达式的处理取决于 table 达式包含哪种类型的值:
-
如果存在任何近似值,则该 table 达式为近似值,并使用浮点算法对其求值。
-
如果没有近似值,则 table 达式仅包含精确值。如果任何精确值包含小数部分(小数点后的值),则使用DECIMAL精确算术对 table 达式求值,并且精度为 65 位数。术语“精确”受可以用二进制 table 示的限制。例如,
1.0/3.0
可以用十进制 table 示法近似为.333...
,但不能写为确切的数字,因此(1.0/3.0)*3.0
的计算结果并不完全是1.0
。 -
否则,table 达式仅包含整数值。该 table 达式是精确的,并且使用整数算术求值,并且精度与BIGINT(64 位)相同。
如果数字 table 达式包含任何字符串,则将它们转换为双精度浮点值,并且该 table 达式为近似值。
插入数字列受 SQL 模式影响,该模式由sql_mode系统变量控制。 (请参阅第 5.1.10 节“服务器 SQL 模式”。)以下讨论提到了严格模式(由STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式值选择)和ERROR_FOR_DIVISION_BY_ZERO。要打开所有限制,您可以简单地使用TRADITIONAL模式,其中包括严格模式值和ERROR_FOR_DIVISION_BY_ZERO:
SET sql_mode='TRADITIONAL';
如果将数字插入精确类型列(DECIMAL或整数),则在列范围和精度范围内,将以其精确值插入数字。
如果该值的小数位数过多,则四舍五入并生成一个音符。如第 12.22.4 节“舍弃行为”中所述进行舍入。即使在严格模式下,由于小数部分舍入而导致的截断也不是错误。
如果该值在整数部分中包含太多数字,则它太大(超出范围),并按以下方式处理:
-
如果未启用严格模式,则该值将被截断为最接近的合法值并生成警告。
-
如果启用严格模式,则会发生溢出错误。
对于DECIMALLiterals,除了 65 位的精度限制外,Literals 文本的长度也有限制。如果该值超过大约 80 个字符,则会发生意外的结果。例如:
mysql> SELECT
CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val;
+------------------+
| val |
+------------------+
| 9999999999999.99 |
+------------------+
1 row in set, 2 warnings (0.00 sec)
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------+
| Warning | 1292 | Truncated incorrect DECIMAL value: '20' |
| Warning | 1264 | Out of range value for column 'val' at row 1 |
+---------+------+----------------------------------------------+
2 rows in set (0.00 sec)
未检测到下溢,因此未定义下溢处理。
对于将字符串插入数字列,如果字符串具有非数字内容,则按以下方式处理从字符串到数字的转换:
-
不以数字开头的字符串不能用作数字,并且在严格模式下会产生错误,否则会发出警告。这包括空字符串。
-
可以转换以数字开头的字符串,但尾随的非数字部分将被截断。如果截断的部分包含空格以外的其他内容,则在严格模式下会产生错误,否则会发出警告。
默认情况下,被零除会产生NULL
的结果,并且没有警告。通过适当设置 SQL 模式,可以限制除以零。
启用ERROR_FOR_DIVISION_BY_ZERO SQL 模式后,MySQL 处理零除的方式不同:
-
如果未启用严格模式,则会发生警告。
-
如果启用严格模式,则禁止插入和除以零的更新,并且会发生错误。
换句话说,涉及执行零除 table 达式的插入和更新可被视为错误,但这除了严格模式外还需要ERROR_FOR_DIVISION_BY_ZERO。
假设我们有以下语句:
INSERT INTO t SET i = 1/0;
严格模式和ERROR_FOR_DIVISION_BY_ZERO模式的组合会发生这种情况。
sql_mode Value | Result |
---|---|
'' (默认) |
没有警告,没有错误; i 设置为NULL 。 |
strict | 没有警告,没有错误; i 设置为NULL 。 |
ERROR_FOR_DIVISION_BY_ZERO | 警告,没有错误; i 设置为NULL 。 |
strict,ERROR_FOR_DIVISION_BY_ZERO | 错误条件;没有插入行。 |