使MySQL不将字符串转换为数字

使MySQL不将字符串转换为数字,mysql,sqldatatypes,type-conversion,Mysql,Sqldatatypes,Type Conversion,我的应用程序中有一个查询,它通过ID或用户名从表中选择用户: SELECT * FROM users WHERE id = '$x' OR username = '$x' 当给定的用户名如foo,bar123或ID如1,123时,这一点就起作用了。 但是当我给出一个像2foo这样的用户名时,它会同时选择用户2foo和id=2的用户。因此它使用2foo的2来查找用户。此外,我还收到一条警告消息:1292:截断了不正确的双精度值:2foo 有没有办法告诉MySQL不要进行这种转换(对于这个查询,而

我的应用程序中有一个查询,它通过ID或用户名从表中选择用户:

SELECT * FROM users WHERE id = '$x' OR username = '$x'
当给定的用户名如
foo
bar123
或ID如
1
123
时,这一点就起作用了。 但是当我给出一个像
2foo
这样的用户名时,它会同时选择用户
2foo
和id=2的用户。因此它使用
2foo
2
来查找用户。此外,我还收到一条警告消息:1292:截断了不正确的双精度值:2foo


有没有办法告诉MySQL不要进行这种转换(对于这个查询,而不是整个数据库)?或者我需要在查询后进行过滤以丢弃错误的结果吗?

您的查询的形成方式会触发MySQL中的“this-is-a-feature-not-a-bug”行为:将相同的字符串(“$x”)与数字字段(id)和varchar字段(用户名)进行比较

虽然我确信,有一些方法可以在SQL中实现这一点,但我怀疑唯一正确的方法是修复创建查询的PHP。差不多

if (is_numeric($x)) $sql="SELECT * FROM users WHERE id = '$x' OR username = '$x'";
else $sql="SELECT * FROM users WHERE username = '$x'";
应该有帮助

以下是SQL版本,只是为了完整起见:

SELECT * FROM users WHERE id = IF('$x' REGEXP '^[0-9]+$','$x',0) OR username = '$x'

注意:从OQ中,我假设$x已经转义。

您能分享构建实际查询的相关代码吗?这很可能不是mysql中的问题,而是生成的问题。我将此查询输入mysql查询浏览器:
SELECT*FROM users,其中id='2foo'或username='2foo'
。由于我从应用程序中将此查询识别为有问题的查询,因此没有周围的代码。MySQL版本:5.1.41-3ubuntu12.10正确的做法是检查$x是否是一个数字,并相应地构建查询:
if(is_numeric($x)){$sql=“SELECT*FROM users,其中id=$x或username='$x''}else{$safeX=MySQL\u real\u escape\u string($x);//或准备好的语句,或任何您喜欢的语句。$sql=“SELECT*FROM username='$x'}
出于好奇,如果用户使用用户名'123'注册,你会怎么做?@JoryGeerts这是我现在的解决方案,非常感谢你的想法(将其作为获得投票的答案发布)(1)REGEXP将匹配'2foo'-你需要在两端锚定它。(2)我建议
如果(val REGEXP…,val,NULL)
,因为OP的表中可能有一个等于零的
id
,但不会有一个等于NULL的id。我的坏,修复了正则表达式。至于0/NULL,我非常确定users表有id int auto_increment…你怎么能确定?你看到OP的DDL了吗?那正好是为了在auto_increment列中存储零呢不能确定!但从OQ的语气和内容来看,我认为OP将能够根据需要调整SQL,如果(并且仅当)他选择不同意我的建议去修理这台机器PHP@EugenRieck@pilcrow我用你的建议来区分is_numeric/is_string。使用
if
在每个查询列上有两个带索引的SQL查询要比使用正则表达式快,我认为它也是更干净的代码。ID确实是自动递增的主键。”“这是一个功能,不是一个bug,而是一个无缺点的警告”;)