使 MySQL 不将字符串转换为数字
Posted
技术标签:
【中文标题】使 MySQL 不将字符串转换为数字【英文标题】:Make MySQL not to convert string to number 【发布时间】:2012-02-06 03:06:35 【问题描述】:我的应用程序中有一个查询,它按 ID 或用户名从表中选择用户:
SELECT * FROM users WHERE id = '$x' OR username = '$x'
当给定用户名foo
、bar123
或1
、123
等ID 时,此功能有效。
但是,当我提供像2foo
这样的用户名时,它会同时选择用户2foo
和id=2
的用户。所以它需要2foo
的2
并找到一个用户。此外,我收到一条警告消息:1292:截断不正确的 DOUBLE 值:2foo。
有没有办法告诉 mysql 不要进行这种转换(对于这个查询而不是整个 db)?还是我需要在查询后进行过滤以丢弃错误结果?
【问题讨论】:
您能分享构建实际查询的相关代码吗?这很可能不是mysql的问题,而是生成的问题。 我在 MySQL 查询浏览器中输入了这个查询:SELECT * FROM users WHERE id = '2foo' OR username = '2foo'
。没有周围的代码,因为我将此查询标识为我的应用程序中有问题的查询。 MySQL版本:5.1.41-3ubuntu12.10
正确的做法是检查 $x 是否是一个数字并相应地构建您的查询:if(is_numeric($x)) $sql = "SELECT * FROM users WHERE id = $x OR username = '$x'" else $safeX = mysql_real_escape_string($x); // Or prepared statements, or whatever else you prefer. $sql = "SELECT * FROM users WHERE username = '$x'"
出于好奇,如果用户使用用户名 '123' 注册,你会怎么做?
@JoryGeerts 这是我现在的解决方案,非常感谢您的想法(将其发布为获得投票的答案)
【参考方案1】:
您的查询是以某种方式形成的,它会在 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 已经被转义了。
【讨论】:
(1) REGEXP 将匹配 '2foo' - 你需要在两端都锚定它。 (2) 我建议IF(val REGEXP ..., val, NULL)
,因为在 OP 的表中可能有一个等于零的id
,但不会有一个等于 NULL 的 id。
我的错,修复了正则表达式。至于 0/Null 我很确定 users 表有 id int auto_increment ...
你怎么能确定?你看到 OP 的 DDL 了吗? NO_AUTO_VALUE_ON_ZERO 呢,正好用于在 AUTO_INCREMENT 列中存储零?
我不能确定!但是从 OQ 的语气和内容来看,我认为 OP 将能够根据他的需要调整 SQL,如果(且仅当)他选择不接受我的建议来修复 PHP
@EugenRieck @pilcrow 我用你的建议来区分 is_numeric/is_string。使用if
在每个查询列上都有两个带有索引的SQL 查询比我认为使用正则表达式要快,而且它的代码也更简洁。 ID 确实是自动递增的主键。 “这是一个功能,不是一个错误,但没有一个少的抛出警告”;-)以上是关于使 MySQL 不将字符串转换为数字的主要内容,如果未能解决你的问题,请参考以下文章
如何在不将 LocalDateTime 字段转换为扩展的 json 对象的情况下将 java 对象转换为简单的 json 字符串?