【问题标题】:MySQL returning LIKE results, when explicit is expectedMySQL 返回 LIKE 结果,当需要显式时
【发布时间】:2016-09-15 09:18:42
【问题描述】:

我在 MySQL 中有下表:

Category.ID [ INT(1), UNSIGNED, NOT NULL, AUTO_INCREMENT ]
1
2

当我运行以下查询时:

SELECT `ID` FROM `Category` WHERE `ID` = '1A';

返回:

Category.ID
1

我正在运行 MySQL Ver 14.14 Distrib 5.7.15,适用于 Linux (x86_64)。

有人可以解释为什么 MySQL 在定义 = 时返回 LIKE 结果吗?

这是不是可以在 my.cnf 中“关闭”的东西?

谢谢。

【问题讨论】:

标签: mysql


【解决方案1】:

这与like无关,MySQLconverts data types while evaluating expressions是这样的。不,这不能在配置文件中关闭。

正如文档所述,MySQL 将数字 1 和字符串 1A 都转换为浮点数。 MySQL 通过从左到右一个一个地检查字符来将字符串转换为数字,并在第一个字符不能作为数字的一部分进行评估时停止,并返回迄今为止处理的字符作为数字。对于字符串1A,字母A是MySQL不能解释为数字的第一个字符,因此返回1作为数值。

你可以做些什么来避免这种情况:

  1. 使用cast()concat() 将数值转换为字符串。在这种情况下,您将失去对 id 字段进行索引搜索的可能性。
  2. 首先检查应用程序中的输入参数,如果不是数字,则根本不进行搜索。

【讨论】:

  • 感谢您的回答。但是,以下查询:SELECT ID FROM Category WHERE ID = CAST('1A' AS CHAR); 仍然返回1 的结果。我尝试了很多查询,从 CAST 到 CONVERT 再到 REGEX,我认为不可能在这里构造一个不返回结果的查询,其中 WHERE 限定符为= '1A'
  • 因为您将字符串文字转换为字符串,而不是将数字 ID 列转换为字符串。我写道:“将数值转换为字符串...
  • 我想通了,谢谢。 SELECT ID FROM Category WHERE CAST(ID as CHAR) = '1A';
  • 顺便说一句,是的,我知道这最好在业务方面完成,然后再构建查询。这是一个理解为什么 MySQL 会以这种方式返回结果的练习。此行为与其他 RDBMS 不一致。
  • 是的,我同意这种行为与其他 rdbms 产品不一致。而且我确实相信这种行为至少应该是可配置的,类似于 MySQL 对标准采取更宽松的方法的其他地方。但是,这种行为在 MySQL 中有很好的记录,并且多年来已被广泛讨论。
【解决方案2】:

您的列类型是INT(1),因此该列是一个值长度为1 的整数,但您要搜索的值是'1A',一个2 个字符的VARCHAR。像 PHP 一样,MySQL 会尽可能地将值转换为它给定的列,你给它一个字符串 (VARCHAR) 值,但该列是一个 INT,所以 [以一种全面的方式,总结了漫长的过程 em>] 它将字符串 "1A" 转换为整数值。

所以值被强制转换为 int 和 (string)1A == (int)1

所以结果是

Category.ID
1

强制数据类型时,PHP 中也会发生同样的情况。

【讨论】:

  • 为了准确起见,字符串被转换为浮点数,而不是int。
  • 真的吗?哇....浮点数本质上是不准确的。在我早期的 SQL 记录价格时,我发现这一点尤其明显,float 列类型会出现各种分数变化。
  • 是的,没错。但是,如果所涉及的数字都是整数,这应该不是问题。
猜你喜欢
  • 1970-01-01
  • 2020-08-31
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
相关资源
最近更新 更多