Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  Functions and Operators  /  Type Conversion in Expression Evaluation

14.3 表达式求值中的类型转换

当操作符与不同类型的操作数一起使用时,类型转换将发生,以使操作数兼容。一些转换将隐式发生。例如,MySQL 将字符串自动转换为数字,并反之。

mysql> SELECT 1+'1';
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

还可以使用 CAST() 函数将数字转换为字符串。隐式转换也将发生在使用 CONCAT() 函数时,因为它期望字符串参数。

mysql> SELECT 38.8, CAST(38.8 AS CHAR);
        -> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
        -> 38.8, '38.8'

请在本节后面查看隐式数字到字符串转换的字符集信息,以及适用于 CREATE TABLE ... SELECT 语句的修改规则。

以下是比较操作的转换规则:

  • 如果一个或两个参数是 NULL,比较的结果是 NULL,除非使用 <=> 等值比较操作符。在 NULL <=> NULL 中,结果为真。无需转换。

  • 如果比较操作的两个参数都是字符串,则将它们比较为字符串。

  • 如果两个参数都是整数,则将它们比较为整数。

  • 十六进制值将被视为二进制字符串,如果不与数字进行比较。

  • 如果一个参数是 TIMESTAMPDATETIME 列,并且另一个参数是常量,常量将被转换为时间戳,以便与时间戳进行比较。这是为了提高 ODBC 的兼容性。对于 IN() 的参数,不执行此操作。为了安全,始终使用完整的日期、时间或时间字符串进行比较。例如,在使用 BETWEEN 进行日期或时间比较时,使用 CAST() 将值转换为所需的数据类型。

    单行子查询从表或表中获取的结果将被视为常量。例如,如果子查询返回一个整数,以便与 DATETIME 值进行比较,比较将被执行为两个整数。整数不会被转换为时间戳。要将子查询值转换为 DATETIME,使用 CAST() 将子查询值转换为 DATETIME

  • 如果一个参数是十进制值,比较依赖于另一个参数。如果另一个参数是十进制或整数值,两个参数将被比较为十进制值。如果另一个参数是浮点值,两个参数将被比较为浮点值。

  • 在所有其他情况下,参数将被比较为浮点数(双精度)。例如,对字符串和数字操作数的比较将发生浮点数比较。

有关将值从一个时间类型转换到另一个时间类型的信息,请见第13.2.8节,“日期和时间类型转换”

JSON值的比较发生在两个级别上。第一个级别的比较基于比较的JSON类型。如果类型不同,比较结果由哪个类型具有更高的优先级决定。如果两个值具有相同的JSON类型,第二级别的比较将使用类型特定的规则。对于JSON和非JSON值的比较,非JSON值将被转换为JSON,并将值比较为JSON值。有关详细信息,请见JSON值的比较和排序

以下示例illustrates将字符串转换为数字以进行比较操作:

mysql> SELECT 1 > '6x';
        -> 0
mysql> SELECT 7 > '6x';
        -> 1
mysql> SELECT 0 > 'x6';
        -> 0
mysql> SELECT 0 = 'x6';
        -> 1

在将字符串列与数字进行比较时,MySQL不能使用索引快速查找值。如果str_col是索引字符串列,索引不能在以下语句中使用:

SELECT * FROM tbl_name WHERE str_col=1;

原因是,有许多不同的字符串可能将被转换为值1,例如'1'' 1''1a'

浮点数和大值的比较INTEGER类型是近似的,因为整数将被转换为双精度浮点数之前比较,这不能代表所有64位整数。例如,整数值253+1不能被表示为浮点数,并将被舍入到253或253+2,取决于平台。

为了illustrate,以下比较返回true(1),但只有第一个比较返回等值:

mysql> SELECT '9223372036854775807' = 9223372036854775807;
        -> 1
mysql> SELECT '9223372036854775807' = 9223372036854775806;
        -> 1

在将字符串转换为浮点数和将整数转换为浮点数时,不一定会发生相同的转换。整数可能被CPU转换为浮点数,而字符串则被逐个字符转换在浮点乘法操作中。结果也可能受到计算机架构、编译器版本或优化级别等因素的影响。避免这些问题的一种方法是使用CAST(),以便将值转换为浮点数:

mysql> SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806;
        -> 0

有关浮点比较的更多信息,请见第B.3.4.8节,“浮点值的问题”

服务器包括dtoa,一个转换库,提供了将字符串或DECIMAL值转换为近似值(FLOATDOUBLE)的基础:

  • 跨平台的一致性转换结果,消除了例如Unix和Windows转换差异。

  • 对值的精确表示,在之前的结果中没有提供足够的精度的场景中,例如在IEEE极限附近的值。

  • 将数字转换为字符串格式,以尽可能高的精度。dtoa 的精度总是与标准C库函数相同或更好。

由于这个库的转换结果在某些情况下与非dtoa结果不同,存在应用程序之间的不兼容性。例如,依赖于特定精度结果的应用程序可能需要调整以适应额外的精度。

dtoa 库提供了以下属性。D 表示具有DECIMAL或字符串表示的值,F 表示在native binary(IEEE)格式中的浮点数。

  • F -> D 转换使用尽可能高的精度,返回D 作为最短的字符串,该字符串在被读回并四舍五入到native binary格式的最近值。

  • D -> F 转换使得F 是输入十进制字符串D 的最近native binary数。

这些属性暗示F -> D -> F 转换除非F-inf+infNaN,否则是无损的。后三个值不受支持,因为SQL标准将它们定义为无效的值。

对于D -> F -> D 转换,一个足够的条件是D 使用15个或更少的数字精度,不是denormal值、-inf+infNaN。在某些情况下,转换是无损的,即使D 有超过15个数字精度,但这不是总是如此。

隐式将数字或时间值转换为字符串时,产生的值的字符集和排序规则由character_set_connectioncollation_connection系统变量确定。这些变量通常使用SET NAMES设置。关于连接字符集的信息,请见第12.4节,“连接字符集和排序规则”

这意味着这种转换结果是一个字符(非二进制)字符串(一个CHARVARCHARLONGTEXT值),除非连接字符集设置为binary。在这种情况下,转换结果是一个二进制字符串(一个BINARYVARBINARYLONGBLOB值)。

对于整数表达式,前面的关于表达式evaluation的注释在assignment时有一些不同;例如,在以下语句中:

CREATE TABLE t SELECT integer_expr;

在这种情况下,表达式的结果列的类型是INTBIGINT,取决于整数表达式的长度。如果整数表达式的最大长度不适合在INTBIGINT中,则使用BIGINT。长度来自SELECT结果集元数据的max_length值(见C API Basic Data Structures)。这意味着可以强制使用BIGINT而不是INT通过使用足够长的表达式:

CREATE TABLE t SELECT 000000000000000000000;