【问题标题】:How does MySQL handle exotic between statementsMySQL如何处理语句之间的奇异
【发布时间】:2017-05-30 14:56:57
【问题描述】:

我有一个介于两者之间的情况,其中表达式既不是计算也不是字段。 不知何故,这是有效的 SQL,对于这种系统,不同排列的结果会给出不同的结果。

我试图弄清楚 MySQL 做了什么,但我无法理解任何模式或任何意义。

这是查询示例:

SELECT 
*
FROM
<table>
WHERE
status = 'test'
BETWEEN
2 AND
'test';

随意替换值和数据类型。

我希望能提示一下这里究竟会发生什么。

【问题讨论】:

标签: mysql


【解决方案1】:

status = 'test' 的结果是真或假,在 MySQL 中等于 1 或 0。

BETWEEN 2 AND 'test' 在 MySQL 中转换为 BETWEEN 2 AND 0

x BETWEEN a AND b 转换为 x &gt;= a AND x &lt;= b

所以条件永远不会满足:

1 >= 2 AND 1 <= 0 => false
2 >= 2 AND 2 <= 0 => false

查询不应返回任何行。

更正:这表明MySQL不解释

WHERE status = 'test' BETWEEN 2 AND 'test'

作为

WHERE (status = 'test') BETWEEN 2 AND 'test'

但是作为

WHERE status = ('test' BETWEEN 2 AND 'test')

我认为这是一个缺陷。 (编辑:我查了一下;它一个缺陷。比较运算符= 应该优先于BETWEENhttps://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html。)

无论如何:

  • ('test' BETWEEN 2 AND 'test') 始终为 false,在 MySQL 中为 0。
  • 如果 status 是一个字符串列,则转换为整数的 status 对于大多数字符串都会产生 0。仅当字符串以整数开头时,该整数才会转换为数字。例如。 '123ABC' 结果为 123。
  • 如果状态是数字列,则不会进行转换。
  • 如果 status 是一个布尔列,它将被转换为 0 表示 false 和 1 表示 true。
  • 所以有些行会返回,有些则不会。

【讨论】:

  • 但在我的情况下它实际上返回结果,这很奇怪。已测试:状态本身有一个真结果:返回所有数据 已测试:状态本身有一个假结果:返回所有数据
  • 糟糕,是的,我必须尝试一下。不知何故,BETWEEN 优先于=,这是我没想到的。我已经更正了我的答案。
  • id = 5 BETWEEN 1 AND 10 // 注意:我有一条 id = 5 的记录 // 结果为假
  • 您是说状态是数字列,而一行的状态是 5?这将导致该行的 WHERE 5 = 0 为 false,因此查询不会返回该行。
  • 小心,应该提到我尝试了一个不同的字段 id,它是一个数字。我做了这个测试来简化字符串的分组和比较。编辑:你是怎么得出 5=0 的?
【解决方案2】:

来自MySQL documentation

如果 expr 大于等于 min 且 expr 小于等于 max,则 BETWEEN 返回 1,否则返回 0。这相当于表达式 (min 否则根据第 12.2 节“表达式求值中的类型转换”中描述的规则进行类型转换,但适用于所有三个参数。

所以 BETWEEN 对整数和字符串的操作方式相同。 MySQL 正在进行类型转换以便能够计算此操作。这是ANSI standard 的一部分。

例如:

// returns true
select ('C' BETWEEN 'A' AND 'D');

或者更有趣:

//also returns true
select ('test' BETWEEN 'test' AND 'testa');

更多信息请查看herehere

【讨论】:

  • status = 'teste' BETWEEN 'test' AND 'testd' // 这似乎总是正确的。如果我理解正确,它应该与您的解释相冲突,因为 e 在 d 之后。不是吗?
  • select ('teste' BETWEEN 'test' AND 'testd');为我返回 false;你能写出完整的查询以便我检查吗?
  • 基本上只添加 select 和 from,出了问题的例子。我应该补充一点,我的条目在列状态下具有“测试”。其他 2 个(teste 和 testd)是虚构的,不作为真实状态存在。
  • 我设法像这样重现您的查询:select 'test' = 'teste' BETWEEN 2 AND 'test';但无论我改变什么,我总是真实的。例如 select 'test' = 'teste' BETWEEN 4 AND '';也返回真。会考虑的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多