2014-09-29 63 views
2

這裏是我的僞查詢:爲什麼num IN(「num1,num2」)在第一個逗號頂部?

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()。爲什麼在第一次遇到逗號時停下來。

回答

2

EDIT在此答案中的表達實例上的字符串上下文完全基於,即,字符數據類型的比較。這些例子沒有考慮隱式數據類型轉換,以及字符串到數字轉換的奇怪的MySQL語義,例如'2,5,7'+0的計算結果爲整數值2.請參閱波希米亞語對此行爲示範的出色答案。)


表中的行具有類別值'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該攔着在第一個逗號中,它是從字符串到數字的隱式轉換,即「以第一個逗號停止」(不僅僅是逗號,它是在字符串不能再轉換爲數字值時遇到的任何字符,而且可能會成爲父母,'#','b'或其他)。IN比較運算符不會爲字符串中的逗號字符提供老鼠的@ss。這些只是字符串中的字符。 內的逗號的字符串值爲而不是解釋爲SQL文本的一部分。

+0

很好的使用微示例,我認爲它們是一個很好的方法來展示問題。 – user2864740 2014-09-29 02:18:43

+0

+1,很好的解釋@ spencer7539 – radar 2014-09-29 02:31:14

+0

謝謝比較操作的例子和詳細解釋。 – SpaceMonkey 2014-09-30 00:29:19

3

IN適用於設置的值爲,而不是單個以逗號分隔的字符串值。提供給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()

+0

+1。恰好解釋道。 – spencer7593 2014-09-29 02:17:16

3

它爲什麼只在第一個值上工作?

爲了將字符串值與數字列進行比較,mysql將單個字符串值轉換爲單個數字值。當MySQL將字符串轉換爲數字,它摒棄一切從第一個非數字字符開始,如:

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

這就是爲什麼只有第一個號碼是有效的。

如果你改變你的字符串值的字符串值的列表,它會工作:

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

+1。我的答案完全錯過了在數值上下文中評估字符串的問題。我的答案中的例子都基於VARCHAR比較。 (我仍然希望有一個sql_mode可以讓MySQL產生關於隱式數據類型轉換的警告。) – spencer7593 2014-09-29 02:37:54

相關問題