使 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'

当给定用户名foobar1231123 等ID 时,此功能有效。 但是,当我提供像2foo 这样的用户名时,它会同时选择用户2fooid=2 的用户。所以它需要2foo2 并找到一个用户。此外,我收到一条警告消息: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 字符串?

从 MemoryStream 获取子字符串而不将整个流转换为字符串

mysql中 日期转换为字符串的函数是啥

如何将数字枚举列转换为 tinyint?

从Int获取单个数字而不使用字符串?