【问题标题】:MySQL strange behavior with comma separated list of numbers逗号分隔的数字列表的MySQL奇怪行为
【发布时间】:2023-03-19 00:40:01
【问题描述】:

我有一个非常复杂的问题,但我把它缩小到这个,首先,让我给你一些测试数据:

运行这个:

CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `value` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

INSERT INTO test (value) VALUES
(1),
('1'),
('1,2'),
('3');

现在运行这个查询:

SELECT * FROM test WHERE value = 1;

我希望在这种情况下只获得前两行,其中值输入为数字 1 或“1”字符,但由于某种原因,这就是我得到的:

1, 1
2, 1
3, 1,2

我的问题是,为什么我得到第三行?

注意:这是我的mysql版本:5.6.28-0ubuntu0.14.04.1

另外,我已经通过使用 FIND_IN_SET 解决了我最初的问题,并且我知道使用这种逗号分隔的列表类型结构并不是一个好主意,也就是说,它可能应该首先使用连接表来完成.不幸的是,我在一个非常大的系统中工作,目前进行这种更改是不切实际的。

我只是对为什么会发生这种特定行为感兴趣。

【问题讨论】:

  • 我们可以拒绝这个问题的前提吗?不要以逗号分隔的数字列表开头。
  • @Strawberry:不管存储逗号分隔的数字列表是否是个好主意,这都是一个好问题。行为出乎意料。
  • 您是否尝试过 InnoDb 表格式相同的行为?
  • 隐式类型转换似乎有些问题。请改用value = '1'
  • 感谢 OP 将复杂问题缩小到特定问题。 +10。

标签: mysql implicit-conversion


【解决方案1】:

得到第三行的原因是隐式数据类型转换由 MySQL 执行。您的查询在 WHERE 子句中有谓词(条件)

  WHERE value = 1

在等式比较运算符(等号)的右侧,我们有一个数字文字。在左侧,我们有一个数据类型为 TEXT 的列。

MySQL 无法对这两种不同的数据类型进行比较。

因此,MySQL 将一侧或另一侧转换为兼容的类型,因此可以执行比较。在这种情况下,MySQL 将列中的值转换为 numeric,因此它与 numeric 文字进行比较。

作为演示,我们可以添加一个零(强制 MySQL 进行转换),并在 SELECT 中显示结果。

 SELECT t.value, t.value + 0 FROM test t

 t.value  t.value + 0
 -------  -----------
 1                  1
 1                  1
 1,2                1
 3                  3

MySQL 参考手册中的某处记录了 MySQL 如何进行转换。冒着错误说明手册内容的风险:MySQL 从左到右逐个字符地读取字符串,直到遇到无法再转换为数字的字符。

如果是字符串'1,2',那恰好是逗号字符。这就是 MySQL 停止的地方。因此,转换返回一个数值 1。您应该指出,其他数据库在尝试将该字符串转换为数字时会抛出错误。但 MySQL 不会抛出错误或警告。

参考:Type Conversion in Expression Evaluation http://dev.mysql.com/doc/refman/5.7/en/type-conversion.html

基本上,查询中的谓词相当于指定:

   WHERE value + 0 = 1

这会强制将 value 列的内容转换为数字,然后与数字文字进行比较。

这就是返回第三行的原因。

要获得不同的结果,请考虑与字符串文字

进行比较
   WHERE value = '1'

【讨论】:

  • 未来读者注意:Postgres 会抛出一个错误,提示 operator does not exist: text = integer
  • @MikeNakis - 人们实现这种类型转换是有原因的。您的 cmets 不具建设性,您甚至不知道 MySQL 严格模式。我不会在这里进行讨论,但是这些 cmets“切换到 X 是足够好的理由”让你看起来像一个初学者。请为了所有正在阅读本文的人以及为了你自己,不要那样做。阅读这些“我现在会在没有任何知识的情况下得出结论”的内容真是太烦人了,它真的对任何人都有帮助。
  • @MikeNakis - 好的,介意自己做,避免用你的无效逻辑影响他人吗?我以为你是初学者,但看起来你是初学者。
  • @MikeNakis - 有些人生活在这个星球上,阅读其他人的名言和想法,却从来没有自己的 - 发生这种情况是有原因的。我已经结束了,我无意与另一个“我也是”的人再争论一次。如果你和你看起来一样粗壮,那我最好用铅笔认真地辩论一下。
  • @MikeNakis 值得注意的是,MySQL 并不孤单。当您在数字上下文中使用字符串时,PHP 和 Javascript 也会这样做。
猜你喜欢
  • 2019-02-14
  • 2010-10-14
  • 2013-07-03
  • 2023-04-06
  • 1970-01-01
  • 2017-06-04
  • 2014-03-16
  • 1970-01-01
相关资源
最近更新 更多