最近作一個批量導入的需求,將多條記錄批量插入數據庫中。解決思路:在程序中封裝一個List集合對象,而後把該集合中的實體插入到數據庫中,由於項目使用了MyBatis,因此打算使用MyBatis的foreach功能進行批量插入。期間遇到了「SQL 命令未正確結束 」的錯誤,最終解決,記錄下來供之後查閱和學習。html
首先,在網上參考了有關Mybatis的foreach insert的資料,具體以下:java
foreach的主要用在構建in條件中,它能夠在SQL語句中進行迭代一個集合。sql
foreach元素的屬性主要有 item,index,collection,open,separator,close。數據庫
item表示集合中每個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程當中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號做爲分隔符,close表示以什麼結束,在使用foreach的時候最關鍵的也是最容易出錯的就是collection屬性,該屬性是必須指定的,可是在不一樣狀況 下,該屬性的值是不同的,主要有一下3種狀況:數組
1.若是傳入的是單參數且參數類型是一個List的時候,collection屬性值爲listoracle
2.若是傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值爲arrayapp
3.若是傳入的參數是多個的時候,咱們就須要把它們封裝成一個Map了,固然單參數也能夠封裝成map學習
而後,照葫蘆畫瓢寫了以下的xml文件,xml
xxxMapper.xml文件:htm
<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>
可是運行起來後就一直報錯,報錯信息以下:
### 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文件修改一下:
<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",將查詢合併結果集。