問題描述:
? ? ? ? 項目場景有一個表一對多的場景,A表一個字段(varchar類型)記錄著B表多條記錄的主鍵(bigint類型)鹏控,中間用逗號隔開佛吓,把A表的字符串轉(zhuǎn)換成list放到B語句查詢霸妹,使用in條件错妖。結(jié)果每次查詢出來的記錄都是字符串的第一個ID對應(yīng)的記錄规辱。
? ? ? ? 例如:select * from t_test where id in('1,2');
? ? ? ? 表記錄:
? ? 執(zhí)行SQL結(jié)果:
排查描述:
1谆棺、通過java代碼日志打印出來的sql,復(fù)制到Navicat中執(zhí)行罕袋,發(fā)現(xiàn)查詢出來的記錄確實一條改淑;
2碍岔、懷疑是Navicat查詢器的問題,把SQL復(fù)制到MySql服務(wù)器上執(zhí)行朵夏,發(fā)現(xiàn)結(jié)果還是一樣蔼啦;
3、發(fā)現(xiàn)in條件中的單引號里面包括的是一個逗號隔開的字符串仰猖,而不是單個捏肢,寫了幾個列子,執(zhí)行結(jié)果如下所示:
? ??
4亮元、懷疑是字符串的問題導(dǎo)致記錄數(shù)猛计,為了再次驗證MySql in條件查詢時候會把字符串強轉(zhuǎn)成int類型,示例如下所示:
5爆捞、從上面的示例得出的結(jié)果奉瘤,在MySql中,如果一個int 類型 + 上一個數(shù)煮甥,MySql會進行類型轉(zhuǎn)換盗温;
6、對于in條件查詢的時候成肘,MySql因為直接傳入一個字符串進去卖局,不做任何處理的話,是會被當成一個值双霍,而不是按照‘砚偶,’分割。MySql在執(zhí)行時候洒闸,會把參數(shù)第一個數(shù)進行轉(zhuǎn)換染坯,如果是第一位是數(shù)字則會把當前的數(shù)字當成查詢的條件,如果是一個字母丘逸,會被強轉(zhuǎn)當成零進行處理单鹿。
解決方法:
1、使用?FIND_IN_SET函數(shù)深纲,
2仲锄、在代碼層進行Arrays.asList進行轉(zhuǎn)換。
對于索引問題:
explain select * from t_test where id in('1,2');? ??
explain select * from t_test where FIND_IN_SET(id,'1,2');
explain select * from t_test where id in('1','2');