为什么num IN(" num1,num2")在第一个逗号顶上?

时间:2014-09-29 01:59:58

标签: mysql sql sql-in

这是我的伪查询:

SELECT col1, col2 FROM table WHERE number IN(number1,number2,number3);

示例

SELECT name, description FROM products WHERE 5 IN(category_id);

注意:我们假设表格中的一行有 category_id = 2,5,7

问题

如果行在逗号分隔集的开头有“5”,则我的查询有效:5,2,7 但是,如果行以除5以外的任何内容开头,则相同的查询不会返回任何结果。

我尝试了各种场景,在我看来,当mysql遇到逗号时,它不再检查匹配的逗号分隔数字。

我检查了所有有意义的内容,例如格式正确的逗号分隔字符串和整理。在这一点上让我感到困惑。任何解决方案?

请注意我使用FIND_IN_SET()并且完美无缺。但是,我不满意在不知道真正问题的情况下放弃IN()。为什么它会在第一次遇到逗号时停止。

3 个答案:

答案 0 :(得分:3)

IN适用于 set 值,而不是单个以逗号分隔的字符串值。提供给IN的每个单独的都是集合中的一个元素

MySQL提供了一个非标准FIND_IN_SET(str, strlist)函数,可以在这里使用,尽管适当的关系数据库设计可以规范化字段。

  

如果字符串str位于由N个子字符串组成的字符串列表strlist中,则返回1到N范围内的值。字符串列表是由以“,”字符分隔的子字符串组成的字符串。

示例:

WHERE FIND_IN_SET('5', category_id)

除了破坏规范化并将参照完整性抛出窗口之外,一个问题是FIND_IN_SET 不能使用索引,因此当用作高基数选择器时可伸缩

另见FIND_IN_SET() vs IN()

答案 1 :(得分:3)

  

为什么它仅适用于第一个值?

为了将字符串值与数字列进行比较,mysql将单个字符串值转换为单个数字。当mysql将字符串转换为数字时,它会从第一个非数字字符开始丢弃所有内容,例如:

  • "1234,5678" - > 1234
  • "abc5678" - > 0

这就是为什么只有第一个号码有效。

如果将字符串值更改为字符串值列表,则可以使用:

 SELECT name, description FROM products WHERE 5 IN ('2', '5', '7');

答案 2 :(得分:2)

编辑此答案中的表达式示例完全基于字符串上下文,即字符数据类型的比较。这些示例不考虑隐式数据类型转换,以及字符串到数字转换的古怪MySQL语义,例如, '2,5,7'+0评估为整数值2.请参阅Bohemian的优秀答案,以证明该行为。)


表中的行具有类别值'2,5,7'。这是一个字符串值。

表达式:

'5' IN ('2,5,7') 

相当于

'5' = '2,5,7'

字符串值中的逗号被视为SQL文本,这些是字符串中的字符。

要获得IN所需的结果,您需要这样的表达式:

'5' IN ('2','5','7')

这是三个单独的值,由逗号分隔,这些逗号是SQL文本的一部分。这相当于:

( '5' = '2'  OR '5' = '5' OR '5' = '7' )

回答你问的问题:

问:为什么它会在第一次遇到逗号时停止?

答:它不会停留在第一个逗号处。它将整个字符串作为单个字符串进行比较。你可以用这个表达式获得相同的结果。

'5' IN ('5,2,7') 

那将返回FALSE,因为它等同于表达式'5'='5,2,7'`,并且被比较的两个字符串不相等。

编辑:上面的示例基于字符串比较。在数字上下文中,字符串'5,2,7'将计算为数值5.

在这种情况下,它仍然不是在第一个逗号停止的IN,它是从字符串到数字的隐式转换,即“停在第一个逗号”。 (它不仅仅是逗号,它是在字符串无法再转换为数字值时遇到的任何字符,可以是paren,'#','b'或其他任何字符。)

底线: IN比较运算符没有给出关于字符串中逗号字符的鼠标@ss。这些只是字符串中的字符。 字符串值中的逗号 被解释为SQL文本的一部分。