最近做一個批量導入的需求,將多條記錄批量插入數據庫中。
解決思路:在程序中封裝一個List集合對象,然后把該集合中的實體插入到數據庫中,因為項目使用了MyBatis,所以打算使用MyBatis的foreach功能進行批量插入。期間遇到了“SQL 命令未正確結束 ”的錯誤,最終解決,記錄下來供以后查閱和學習。
首先,在網上參考了有關Mybatis的foreach insert的資料,具體如下:
foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。
foreach元素的屬性主要有 item,index,collection,open,separator,close。
item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用于表示在迭代過程中,每次迭代到的位置,open表示該語句以什么開始,separator表示在每次進行迭代之間以什么符號作為分隔符,close表示以什么結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,但是在不同情況 下,該屬性的值是不一樣的,主要有一下3種情況:
1.如果傳入的是單參數且參數類型是一個List的時候,collection屬性值為list
2.如果傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值為array
3.如果傳入的參數是多個的時候,我們就需要把它們封裝成一個Map了,當然單參數也可以封裝成map
然后,照葫蘆畫瓢寫了如下的xml文件,
xxxMapper.xml文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
< insert id= "addSupCity" parameterType= "java.util.List" > <selectKey keyProperty= "cityId" order = "BEFORE" resultType= "String" > <![CDATA[ SELECT SEQ_OCL_SUPCITY.NEXTVAL FROM dual]]> </selectKey> INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES <foreach collection= "list" item= "item" index = "index" separator= "," > ( #{item.cityId,jdbcType= VARCHAR }, #{item.cityCode,jdbcType= VARCHAR }, #{item.cityName,jdbcType= VARCHAR }, #{item.areaDesc,jdbcType= VARCHAR }, #{item.supId,jdbcType= VARCHAR }, #{item.stat,jdbcType= VARCHAR } ) </foreach> </ insert > |
但是運行起來后就一直報錯,報錯信息如下:
1
2
3
|
### SQL: INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?) ### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正確結束 |
把SQL復制出來在PL/SQL中運行也是報同樣的錯,如上也可以看出,使用批量插入執行的SQL語句等價于: INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?),而在oracle中用insert into xxx values (xxx,xxx),(xxx,xxx) 這種語法是通不過的 。再回過頭去看那篇文章,發現這是適用于MySQL的,不適用于Oracle,因此把xml文件修改一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
< insert id= "addSupCity" parameterType= "java.util.List" > INSERT INTO T_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) SELECT SEQ_OCL_SUPCITY.NEXTVAL CITY_ID, A.* FROM ( <foreach collection= "list" item= "item" index = "index" separator= "UNION ALL" > SELECT #{item.cityCode,jdbcType= VARCHAR } CITY_CODE, #{item.cityName,jdbcType= VARCHAR } CITY_NAME, #{item.areaDesc,jdbcType= VARCHAR } AREA_DESC, #{item.supId,jdbcType= VARCHAR } SUP_ID, #{item.stat,jdbcType= VARCHAR } STAT FROM dual </foreach> )A </ insert > |
運行通過。
在Oracle的版本中,有幾點需要注意的:
1.SQL中沒有VALUES;
2.<foreach>標簽中的(selece ..... from dual);
3.<foreach>標簽中的separator的屬性為"UNION ALL",將查詢合并結果集。
以上所述是小編給大家介紹的Oracle+Mybatis的foreach insert功能批量插入報錯的快速解決辦法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!