第24章:精度数学 / 24.3. 表达式处理

对于精度数学,只要可能,就会使用给定的准确值数值。例如,在比较中所用的数值与给定的值准确相同,无任何变化。在严格的SQL模式下,对于插入具有准确数据类型(DECIMAL或整数)的列的INSERT操作,如果值在列的允许范围内,将插入具有准确值的数值。检索时,所获得的值与插入的值应是相同(如果未采用严格模式,允许INSERT执行截短操作)。

对数值表达式的处理取决于表达式包含的值的类型:

·         如果存在任何近似值,表达式也是近似的,并将使用浮点算法进行评估。

·         如果不存在近似值,表达式仅包含准确值。如果任一准确值包含小数部分(小数点后面的值),将使用DECIMAL准确算法来计算表达式,其精度为65位数字。术语“准确”受二进制表述方面的限制。例如,1.0/3.0在十进制表述中可近似为.333...,但并不是准确数值,因此(1.0/3.0)*3.0不会被计算为准确的1.0

·         另外,表达式仅包含整数值。表达式是准确的,并将使用整数算法进行计算,其精度与BIGINT的相同(64比特)。

如果数值表达式包含任何字符串,会将其转换为双精度浮点值,表达式是近似的。

数值列中的插入操作受SQL模式的影响,它是由sql_mode系统变量控制的(请参见1.8.2节,“选择SQL模式”)。下面介绍了严格模式(由STRICT_ALL_TABLESSTRICT_TRANS_TABLES模式值选择)RROR_FOR_DIVISION_BY_ZERO。要想打开所有限制,可简单地使用TRADITIONAL模式,它包含严格模式和ERROR_FOR_DIVISION_BY_ZERO

mysql> SET SQL_MODE='TRADITIONAL';

如果将数值插入具有准确类型的列(DECIMAL或整数),如果值在列允许的范围内,将以准确值形式插入数值。

如果数值在其小数部分有过多位,将执行四舍五入操作并给出告警。关于四舍五入的具体介绍,请参见四舍五入一节。

如果数值在其整数部分有过多位,数值过大,并将按下述方式处理:

·         如果未启用严格模式,该数值将被截短为最近的合法值,并发出警告。

·         如果启用了严格模式,将给出溢出错误。

不检测下溢,因而下溢处理是不确定的。

默认情况下,除0操作会导致NULL结果,不产生告警。启用了ERROR_FOR_DIVISION_BY_ZERO SQL模式后,MySQL会以不同方式处理除0问题:

·         如果未启用严格模式,发出警告。

·         如果启用了严格模式,将禁止包含除0操作的插入和更新,并给出错误。

换句话讲,对于包含执行除0操作的表达式的插入和更新,将被当作错误对待,但除了严格模式外还需要ERROR_FOR_DIVISION_BY_ZERO

假定下述语句:

INSERT INTO t SET i = 1/0;

对于严格模式和ERROR_FOR_DIVISION_BY_ZERO模式的组合,情况如下:

sql_mode

结果

'' (Default)

无告警,无错误:i被设置为NULL

strict

无告警,无错误:i被设置为NULL

ERROR_FOR_DIVISION_BY_ZERO

告警,无错误:i被设置为NULL

strict,ERROR_FOR_DIVISION_BY_ZERO

错误条件,不插入任何行。

将字符串插入数值列时,如果字符串具有非数值内容,将按下述方式将字符串转换为数值:

·         对于未以数值开始的字符串,在严格模式下,不能将其作为数值使用,并会产生错误,在其他情况下,给出警告。包括空字符串。

·         对于以数值开始的字符串,可以进行转换,但尾随的非数值部分将被截去。在严格模式下会导致错误,在其他情况下,给出警告。