我正在做一些系统测试,并期望从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在这里做什么?
答案 0 :(得分:7)
MySQL通过类型转换快速而轻松地运行。在将char隐式转换为数字时,只要字符是数字,它将从字符串的开头开始提取字符,而忽略其余字符。在您的示例中,xxx
不是数字,因此MySQL仅采用首字母“ 20”。
解决此问题的一种方法(这对性能来说是可怕的,因为您失去了列上可能使用的索引的用法),是将数字侧显式转换为字符:
SELECT * FROM transactions WHARE (CAST id AS CHAR) = 20;
编辑:
从注释中重述关于性能的讨论-在客户端执行强制转换为数字可能是最好的方法,因为它使您可以避免在不知道应返回任何行的情况下(例如,当输入的数字无效,例如“ 20x”。
另一种方法是将输入转换为数字,然后再次转换为字符串,然后比较长度。如果长度相同,则表示输入字符串已完全转换为数字,并且未省略任何字符。 WRT性能应该不错,因为此比较是对输入的字符串而不是列中的值执行的,并且如果条件通过了输入的短路评估,则仍可以使用列的索引:
SELECT *
FROM transactions
WHARE LENGTH(:input) = LENGTH(CAST(:input AS SIGNED)) AND id = :input;