在mysql中隐式转换数字

时间:2017-09-15 09:03:08

标签: mysql casting implicit-conversion

表格结构:

CREATE TABLE `test_table` (
  `pk_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(30) NOT NULL,
  `password` varchar(128) NOT NULL,
  `version` bigint(20) NOT NULL,
  PRIMARY KEY (`pk_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551601 DEFAULT CHARSET=utf8;

数据:

/*
-- Query: SELECT * FROM test_table
-- Date: 2017-09-15 16:51
*/
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (10545342555594296735,'testabc','testabc',5);
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (10545342555594297155,'testdef','testdef',0);
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (10545342555594298139,'testghi','testghi',0);
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (18446744073709551601,'testjkl','testjkl',0);
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (18446744073709551602,'testmno','testmno',0);
INSERT INTO `test_table` (`pk_id`,`name`,`password`,`version`) VALUES (18446744073709551603,'testpqr','testpqr',0);

运行sql:

SELECT 
    *
FROM
    test_table
WHERE
    CAST(pk_id AS CHAR) = 18446744073709551601;

结果:

# pk_id, name, password, version
'18446744073709551601', 'testjkl', 'testjkl', '0'
'18446744073709551602', 'testmno', 'testmno', '0'
'18446744073709551603', 'testpqr', 'testpqr', '0'

我对隐式转换感到困惑,发生了什么?我已经检查了official website关于隐式转换规则。但我仍然不了解。有人可以帮助我。

1 个答案:

答案 0 :(得分:1)

您可以查看此link以获取有关类型转换的更多信息。

  

以下规则描述了比较操作的转换方式:

     

1 - 如果一个或两个参数为NULL,则比较结果为NULL,但NULL-safe< =>除外。平等比较运算符。对于NULL< => NULL,结果为true。无需转换。

     

2 - 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。

     

3 - 如果两个参数都是整数,则将它们作为整数进行比较。

     

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

     

5 - 如果其中一个参数是TIMESTAMP或DATETIME列而另一个参数是常量,则在执行比较之前将常量转换为时间戳。这样做是为了更友好的ODBC。请注意,这不是针对IN()的参数!为安全起见,在进行比较时始终使用完整的日期时间,日期或时间字符串。例如,要在将BETWEEN与日期或时间值一起使用时获得最佳结果,请使用CAST()将值显式转换为所需的数据类型。

     

6 - 来自一个或多个表的单行子查询不被视为常量。例如,如果子查询返回要与DATETIME值进行比较的整数,则比较将作为两个整数完成。整数不会转换为时间值。要将操作数作为DATETIME值进行比较,请使用CAST()将子查询值显式转换为DATETIME。

     

7 - 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较,如果另一个参数是浮点值,则将参数作为浮点值进行比较。

     

8 - 在所有其他情况下,将参数作为浮点(实数)进行比较。

在您的情况下,参数将被比较为浮点(实数)。使用浮点数(或转换为浮点数的值)的比较是近似的,因为这些数字是不精确的。这可能会导致结果看起来不一致。

您可以检查以下查询将为VALUE1,VALUE2,VALUE3和VALUE4生成相同的结果。这就是为什么你的查询返回的结果。

SELECT 
    '18446744073709551601' + 0E0 AS VALUE1,
    '18446744073709551602' + 0E0 AS VALUE2,
    '18446744073709551603' + 0E0 AS VALUE3,
     18446744073709551601 + 0E0 AS VALUE4

如果您希望查询按预期运行,则应将两个参数都更改为字符串

CAST(pk_id AS CHAR) = '18446744073709551601';