mybatis中insert into ...select ...from dual union all select ... from dual 提示sql命令未结束的问题

本文介绍了一种在MyBatis中进行批量插入时的优化方法,通过在XML Mapper文件中加入useGeneratedKeys=false属性来避免因主键自动生成而导致的性能问题。这种方法特别适用于需要大量插入数据的场景。

需要在插入时加上useGeneratedKeys="false"

原Mapper:

<insert id="insertProductRoleUser" parameterType="list">	 
	 	INSERT INTO AMC_PRODUCT_ROLE_USER
	   		(user_id, role_id)
		<foreach collection="list" item="productRole" index="index" separator="union all">
			SELECT 
				#{productRole.user_id,jdbcType=VARCHAR},
				#{productRole.role_id,jdbcType=VARCHAR} 
			FROM DUAL
		</foreach> 
    </insert>

新Mapper:

<insert id="insertProductRoleUser" parameterType="list" useGeneratedKeys="false">	 
	 	INSERT INTO AMC_PRODUCT_ROLE_USER
	   		(user_id, role_id)
		<foreach collection="list" item="productRole" index="index" separator="union all">
			SELECT 
				#{productRole.user_id,jdbcType=VARCHAR},
				#{productRole.role_id,jdbcType=VARCHAR} 
			FROM DUAL
		</foreach> 
    </insert>


在 Java 的 XML 文件中编写 Oracle 数据库的批量 `MERGE INTO` SQL 语句时,需要结合 MyBatis 的 `<foreach>` 标签来实现对集合数据的遍历操作,并通过 `MERGE INTO` 实现插入或更新逻辑。由于 Oracle 不支持直接批量插入多值列表的方式,因此通常将 `MERGE INTO` 与 `SELECT ... FROM DUAL` 配合使用,构造多个子查询并通过 `UNION ALL` 拼接成一个完整的源表。 ### 批量 MERGE INTO 示例 以下是一个典型的 XML 中的写法,用于实现批量合并插入/更新: ```xml <insert id="batchMerge"> <trim prefix="BEGIN" suffix="END;"> <foreach collection="list" item="item" separator=";"> MERGE INTO target_table t USING ( SELECT #{item.id} AS id, #{item.name} AS name, #{item.description} AS description FROM DUAL ) s ON (t.id = s.id) WHEN MATCHED THEN UPDATE SET t.name = s.name, t.description = s.description WHEN NOT MATCHED THEN INSERT (t.id, t.name, t.description) VALUES (s.id, s.name, s.description) </foreach> </trim> </insert> ``` 该写法利用了 PL/SQL 块(`BEGIN ... END;`)包裹多个 `MERGE INTO` 语句,并通过分号 `;` 分隔每条语句,确保其作为匿名块执行[^2]。这种方式可以避免因单次执行多条 SQL 语句而引发的语法错误。 ### 处理 CLOB 类型字段 如果目标表中包含 `CLOB` 类型字段,在构造 `SELECT ... FROM DUAL` 子句时需确保字段类型匹配。例如,若某个字段为 `CLOB` 类型,则应显式指定其转换方式,防止出现 `ORA-01790: 表达式必须具有对应表达式相同的数据类型` 错误。可以通过 `TO_CLOB()` 函数进行强制转换: ```xml <insert id="batchMergeWithClob"> <trim prefix="BEGIN" suffix="END;"> <foreach collection="list" item="item" separator=";"> MERGE INTO target_table t USING ( SELECT #{item.id} AS id, TO_CLOB(#{item.content}) AS content FROM DUAL ) s ON (t.id = s.id) WHEN MATCHED THEN UPDATE SET t.content = s.content WHEN NOT MATCHED THEN INSERT (t.id, t.content) VALUES (s.id, s.content) </foreach> </trim> </insert> ``` 此方法可有效解决因字段类型不一致导致的 SQL 异常问题[^1]。 ### 注意事项 - `MERGE INTO` 语句中,`ON` 条件字段不能参与更新操作,否则会引发语法错误。 - 若存在大量数据更新,建议考虑分批次提交以提升性能和事务控制能力。 - 在使用 `<foreach>` 时,需正确设置 `separator`, `open`, `close` 属性,以适应 PL/SQL 语法要求。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值