1. 程式人生 > >記一個mysql使用時in()內字串長度截斷的問題

記一個mysql使用時in()內字串長度截斷的問題

眾所周知,mysql對in內的數量和長度是沒有限制的(當然我也是百度才確認的^_^),那麼為什麼會有in內的內容被截斷的問題呢?先看下報錯日誌如下

 .......|mybatis|select * from user_acct where user_id in ('e1035711b70a4b46aaf3f622617ccd00','e105604d110c46338f164b54db9a9d40','e1080ae78c034bb08e8ff084463f3275','e10ee307d07b40a18e8c1218d104938b','e10fbf6943ff4f219aaef02a173fa8f8','e114724745514f7d8ed15a1a72002d77','e11efc56ef144cff9509f62846a2eeb1','e123a55c6b3f44a7be2523ed5e253953','e1294c3b54774d10883486b9eafdcba3','e12f318594524d3e88ece35224086fef','e139463f5e30403fba138fccca028ad1','e14a783a73094fe0b0ea30a0fe3703eb','e1585e28f7bc4af7b589b3c9a8a80f1b','e15ffddccd6e409086b8d9a267411f7f','e168c71ac82c48c3ad9125a5614eba59','e16a0d2234344257ae7b9048380fe3de','e16ba2f5472b46d5ac5ce92ddded3bde','e16d519f16584a9f9ce3364ef1b51ed0','e171e4698ee54e22b183ad69fe5a21f4','e17555068fd84f579b09b866598cdd64','e1777e9028be4cda829651732b036f1b','e17b4fd3fdc5497280d44871a8518ee0','e18a261edb3147ebaa8217a1b5f96f0d','e191b891fced43ce90f8c1152e25e3e3','e1930b1f53ea43058a71db7859a2a678','e19cca9de073448e9409d11cccea0ed9','e1c01de6b8d74a2b82278b345bd5db31','e1c6b23168d643259f873b98dd7255e1','e1cd50f75e1d472386e03abf09325bde','e1dc283b) and
origin=? GROUP BY user_id, acct_type|'ls'|0|java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor54.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49
) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:60) at com.sun.proxy.$Proxy184.query(Unknown Source) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:108) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:102) at sun.reflect.GeneratedMethodAccessor57.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:354) at com.sun.proxy.$Proxy35.selectList(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:194) at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:119) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) at com.sun.proxy.$Proxy44.getByUserIds(Unknown Source) at sun.reflect.GeneratedMethodAccessor166.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at com.alibaba.druid.support.spring.stat.DruidStatInterceptor.invoke(DruidStatInterceptor.java:72) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy45.getByUserIds(Unknown Source) ... 60 more Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0). at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:937) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:872) at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3367) at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3352) at com.mysql.jdbc.PreparedStatement.setString(PreparedStatement.java:4078) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setString(FilterChainImpl.java:2823) at com.alibaba.druid.filter.FilterAdapter.preparedStatement_setString(FilterAdapter.java:1340) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setString(FilterChainImpl.java:2820) at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.setString(PreparedStatementProxyImpl.java:547) at com.alibaba.druid.pool.DruidPooledPreparedStatement.setString(DruidPooledPreparedStatement.java:365) at org.apache.ibatis.type.StringTypeHandler.setNonNullParameter(StringTypeHandler.java:31) at org.apache.ibatis.type.StringTypeHandler.setNonNullParameter(StringTypeHandler.java:26) at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:50) at org.apache.ibatis.type.UnknownTypeHandler.setNonNullParameter(UnknownTypeHandler.java:45) at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:50) at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:81) at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:80) at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:61) at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:74) at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:59) at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267) at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:137) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:96) at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:77) ... 60 more

報錯是說sql中沒有引數,但是我們傳了一個引數,所以引數索引越界

Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

拿到日誌中的sql:

SELECT
    *
FROM
    user_acct
WHERE
    user_id IN (
    'e1035711b70a4b46aaf3f622617c0000',
    'e105604d110c46338f160004db9a9d40',
    ...這裡省略26個user_id
    'e1cd50f75e1d472386e0000f09325bde',
    'e1dc283b) 
    and origin=? GROUP BY user_id, acct_type;

可以看出sql中是有一個引數位的,但是因為最後一個user_id的右引號沒了,所以sql語句把後面全部認為是最後一個左引號的字串了。
我們再拿到程式碼裡面的sql

@Select("select * from user_acct "
            + "where user_id in (${userIds}) and origin=#{origin} GROUP BY user_id, acct_type")
@ResultMap("com.user.dao.UserAcctMapper.UserAcctResult")
List<UserAcct> getByUserIds(@Param("userIds") String userIds, @Param("origin") String origin);

從這裡看,第一反應是mybatis在拼接sql時,佔位符${}內容由於過長被截斷了。
從這裡開始查詢問題,面向百度程式設計:mybatis並不會截斷 ${}內的內容。Defeated!
那麼是mysql的問題麼?再次面向百度:mybatis對整體sql長度有限制,預設1M,但對in()內的長度和個數是沒有限制的。再次Defeated!
最後,會不會是傳過來的這個String userIds就是被截斷的呢?
回溯到拼接這個userIds的地方,是用group_concat拼接的,如下:

SELECT GROUP_CONCAT("'",user_id,"'") FROM  user_info limit 1000;

到這裡基本就能猜出問題所在了,但我們還是確認一下,百度了一下GROUP_CONCAT的長度限制,果然,預設1024位元組,一個userId32位元組,加兩個引號,加一個逗號:(32+2+1)*29+9=1024,剛好。
這裡就需要修改某個引數了:group_concat_max_len。根據我們要1000個userId拼接的要求35*1000=3.5w,我們改成5w,問題解決!

相關推薦

一個mysql使用時in()字串長度截斷的問題

眾所周知,mysql對in內的數量和長度是沒有限制的(當然我也是百度才確認的^_^),那麼為什麼會有in內的內容被截斷的問題呢?先看下報錯日誌如下 .......|mybatis|select * from user_acct where user_id

一個 MySQL Streaming result set 的小錯誤

同事使用kettle遷移MySQL資料時出現了 SQLException,詳細報錯資訊如下: Error reading fro

一個mysql環境RR隔離級別轉換成RC的問題

mysql 事務隔離級別 RR RC先了解RR(REPEATABLE-READ)和RC(READ-COMMITTED)的區別.RR隔離級別增加了間隙鎖,避免了幻讀,並且阻止了不可重復讀,讓同一個事務裏面的查詢和修改都是一致的.mysql默認的隔離級別就是RR.雖然說RC隔離級別在同一個事務內會存在查詢出不同數

mysql 用char_length匹配字串長度

原文地址:https://blog.csdn.net/gaofeiSister/article/details/78939826 如果簡單的字母求長度: mysql> select char_length(“abc“); 就會在一個數據表中顯示3 但當

java創建一個對象存中發生了什麽

就是 抽象方法 abstract getx 對象共享 鼓勵 事情 指定 更多 JAVA是一種面向對象的語言,它本身具有面向對象的三大特性--封裝,繼承,多態。開發時,我們要記住,屬性是用於存儲數據的。直接被訪問,容易出現安全隱患。所以,類中的屬性通常被私有化,並對外提供公共

tomcat啟動存溢出,Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"

通過 per memory tomcat配置 -xmx ... nbsp ont ron 問題原因   通過tomcat啟動項目,也許是因為項目太大,配置的內存不夠用了。老是報內存溢出的問題。 解決辦法 1.選中項目 右鍵 run as -》Run Configu

解決在anaconda下使用pymysql連線資料庫MySQL出現的一個問題

問題描述: pymysql.err.OperationalError: (1045, "Access denied for user 'mel'@'localhost' (using password: NO)") db = pymysql.connect(host="localhost"

教你如何檢查一個函式是否為JavaScript執行環境建函式

在開發過程中,對於某些API在現有的JavaScript執行時環境不支援的時候,我們大都會採用加入polyfill來解決這個問題。但有些時候我們可能需要知道現在某個API到底是否為執行時環境所原生支援,還是polyfill程式碼支援的。今天在學習Vue 2.X版本的原始碼時,就發現了Vue中也有用來檢測一

要求產生10個隨機的字串,每一個字串互相不重複,每一個字串中組成的字元(a-zA-Z0-9)也不相同,每個字串長度為10

public static void main(String[] args) { List<Character> list = new ArrayList<Character>(); Set<String> hashS

使用JSON JavaScriptSerializer 進行序列化或反序列化出錯。字串長度超過了為 maxJsonLength屬性

“/”應用程式中的伺服器錯誤。 使用 JSON JavaScriptSerializer 進行序列化或反序列化時出錯。字串的長度超過了為 maxJsonLength 屬性設定的值。 說明: 執行當前 Web 請求期間,出現未經處理的異常。請檢查堆疊跟蹤資訊,以瞭解有關該錯

使用 JSON JavaScriptSerializer 進行序列化或反序列化出錯。字串長度超過了為 maxJsonLength 屬性設定的值。

最近公司佈置了報表的開發,這個模組涉及到了幾萬條資料的匯入,然後後臺處理,再返回到前臺並顯示出來,不過當我匯入4W條資料的資料,VS已經支援不過來,幾乎卡住,電腦也接近奔潰,不過處理2W條的資料還是沒問題的。 具體如何解決? c#後臺方法,返回值為 string

載入一個,其內部類是否同時被載入?靜態部類單例模式

載入一個類時,其內部類是否同時被載入?下面我們做一個實驗來看一下。  Java程式碼   public class Outer {       static {           System.out.println("load outer class..."); 

mysql 格式化字串長度不夠補0

1.前面補零  LPAD(str,len,padstr) 返回字串 str, 其左邊由字串padstr 填補到len 字元長度。假如str 的長度大於len, 則返回值被縮短至 len 字元。 se

在使用MySql,命令列插入中文資料遇到亂碼問題的解決措施

**造成這種問題的原因是安裝的mysql預設是UTF-8編碼格式,即使你傳輸的資料已經設定GBK編碼,也同樣會報錯。 廢話不多數,解決方式如下; 1,如果你的mysql還在執行中,那就先到工作管理員中停止該服務,如果已經關閉mysql,前面的話當我沒說~。 2.然後進入到你安裝的

解決在IPython3下使用pymysql連線資料庫MySQL出現的一個問題

問題描述: from pymysql import * conn = connect(host=‘localhost’,port=3306,database=‘jing_dong’,user=‘root’,password=‘135790’,charset=‘utf8’) 錯誤型別: Int

傳送資料到PI,出現字串後面多一個空格的問題

業務場景:一個很奇怪的問題,string格式的欄位,傳送到PI後檢視報文發現會在末尾多給一個空格,後來發現基本上是數字、金額等欄位,這些欄位賦值給string後確實是會在後面多一個空格。 解決辦法:使

PHP建的字串長度函式strlen mb_strlen

採用mb_strlen函式可以較好地解決這個問題。mb_strlen的用法和 strlen類似,只不過它有第二個可選引數用於指定字元編碼。例如得到UTF-8的字串$str長度,可以用 mb_strlen($str,'UTF-8')。如果省略第二個引數,則會使用PHP的內部編碼。內部編碼可以通過 mb_int

JS判斷輸入字串長度(漢字算兩個字元,字母數字算一個

<html> <head> <title>js判斷輸入字串長度(漢字算兩個字元,字母數字算一個)</title> <style type="text/css"> .pbt { margin-b

一個案例講解獲取字串長度的函式mb_strlen()和字串擷取函式mb_substr()

這是在專案中遇到的一小段,包含了mb_strlen()和mb_substr()兩個函式: > function _cut($_string,$_strlen){ > if(mb_

C語言之定義一個函式,實現對字串做如下操作:當字元為字母,大小寫互換,當字元為數字,原樣輸出,當有其它字元出現時,結束操作,返回已處理的字串

Action(){       char str[]={"tEst234%^road"};int len = sizeof(str)/sizeof(char);//strTest2呼叫函式lr_output_message("%s",strTest2(str,len)); r