假设用户输入
mysite.com/profile?identity=1
mysite.com/profile?identity=dinodsja
mysite.com/profile?identity=1a
获取值
$identity = $_GET['identity']; // identity can be user_id or user_name
我有一个简单的选择查询:
SELECT * FROM lb_users WHERE (user_id = 'dinodsja' OR user_name = 'dinodsja') AND user_status = 1
它工作正常。但问题是:
SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1
当我执行此查询时,它还会返回结果而不满足条件。
表格结构:
user_id bigint(25)
user_name varchar(50) utf8_general_ci
**
-> Is this a MySQL Bug ?
-> How can we avoid this ?
-> What will be the query ?
**
答案 0 :(得分:31)
答案 1 :(得分:24)
我记得早就遇到过类似的问题了。
首先是一些背景:这是不是一个bug。它实际上是一个功能。好吧,它可能会导致这种意外行为,但MySQL因此非常宽容w.r.t.用户输入,相应的选择查询:
mysql> SELECT 'a' = 'a ';
-> 1
mysql> SELECT 'A' = 'a';
-> 1
因此,对于implicit type conversion,例如,INTEGER中的'1a'
的结果为1,而且:
mysql> SELECT 0 = 'x6';
-> 1
mysql> SELECT 1 = ' 1';
-> 1
mysql> SELECT 1 = ' 1a';
-> 1
此功能也在其他非静态类型语言中实现。例如,PHP调用此type juggling。请参阅文档中的PHP String conversion rules和此示例:
<?php
$foo = "0"; // $foo is string (ASCII 48)
$foo += 2; // $foo is now an integer (2)
$foo = $foo + 1.3; // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)
?>
请参阅JavaScript:
<script>
document.write(parseInt("40 years") + "<br>");
</script>
=> 40
尽管如此,解决问题的方法非常简单:只需将整数转换为char,然后进行比较:
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1' OR user_name = '1')
-> 1
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1a' OR user_name = '1a')
-> 0
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = 'dinodsja' OR user_name = 'dinodsja')
-> 1
我为每个人做了一个小提琴试试:http://sqlfiddle.com/#!2/c2835/14/0
希望有所帮助,
-Hannes
答案 2 :(得分:0)
根据您之前的消息
是个人资料的用户输入。用户可以提供user_id或user_name。 所以输入有效。但没有数据。 - DBK 3月30日6:42
我建议测试一下它是否为整数,只搜索用户ID(如果它是整数)。对于没有处理STRING到INT比较的mySQL来说,这实际上更像是一种解决方法,但它应该可行。
declare @InputVar varchar(10)
set @InputVar = '1a'
SELECT *
FROM lb_users
WHERE
(case when isnumeric(@InputVar) = 1 then
case when (user_id = @InputVar OR user_name = @InputVar) then 1 else 0 end
else
case when user_name = @InputVar then 1 else 0 end
end =1 )
And
user_status = 1
答案 3 :(得分:0)
在处理字符串时,我会使用'LIKE'而不是'='来避免这种静默类型转换的疯狂。 LIKE可以使用字符串,所以为什么不使用它。
答案 4 :(得分:0)
SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1
如果你将'1a'改为1a,你会得到1个结果:
#1064 - 您的SQL语法出错;检查与MySQL服务器版本对应的手册,以便在第1行的“1a LIMIT 0,30”附近使用正确的语法
这不是错误,请查看http://dev.mysql.com/doc/refman/5.0/en/where-optimizations.html
希望这会有所帮助
答案 5 :(得分:0)
我认为你无法复制主键和ID,我测试了那个,我想出了一个正在运行的数据..你设置user_id的属性如下:
user_id bigint(50) auto_increment primary key
这不是mysql错误。