这是我的伪查询:
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()
。为什么它会在第一次遇到逗号时停止。
答案 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 不能使用索引,因此当用作高基数选择器时不可伸缩
答案 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文本的一部分。