MySQL从INT列中选择

问题描述 投票:6回答:1

我正在做一些系统测试,并期望从MySQL(5.7.21)获得空结果,但惊讶地得到结果。

我的交易记录表如下:

Column        Data type
----------------------------
id           | INT
fullnames    | VARCHAR(40)
---------------------------

还有一些记录

--------------------------------
id           | fullnames
--------------------------------
20           | Mutinda Boniface
21           | Boniface M
22           | Some-other Guy
-------------------------------

我的示例查询:

select * from transactions where id = "20"; -- gives me 1 record which is fine
select * from transactions where id = 20; -- gives me 1 record - FINE as well

现在,当我尝试这些时,它变得很有趣:

select * from transactions where id = "20xxx"; -- gives me 1 record - what is happening here?

MySQL在这里做什么?

mysql sql database select type-conversion
1个回答
7
投票

MySQL通过类型转换快速而轻松地发挥作用。在将char隐式转换为数字时,只要字符是数字,它将从字符串的开头开始提取字符,而忽略其余字符。在您的示例中,xxx不是数字,因此MySQL仅采用首字母“ 20”。

解决此问题的一种方法(这对性能来说是可怕的,因为您失去了在列上可能使用的索引的用法)是将数字面显式转换为字符:

SELECT * FROM transactions WHARE (CAST id AS CHAR) = 20; 

编辑:从注释中引用有关性能的讨论-在客户端执行强制转换为数字可能是最好的方法,因为它将使您避免在不知道应返回任何行的情况下(例如,当您输入的数字无效,例如“ 20x”)。

一种替代方法是将输入转换为数字,然后再次转换为字符串,然后比较长度。如果长度相同,则表示输入字符串已完全转换为数字,并且未省略任何字符。 WRT性能应该不错,因为此比较是在输入的字符串上执行的,而不是对列中的值进行的,并且如果条件通过了输入的短路评估,则仍可以使用列的索引:

SELECT *
FROM   transactions 
WHERE  LENGTH(:input) = LENGTH(CAST(:input AS SIGNED)) AND id = :input;
© www.soinside.com 2019 - 2024. All rights reserved.