示例:很普通的需求
表结构:
create table t_user(
user_id varchar2(20),
user_name varchar2(20)
);
java bean:
public class User {
String userId;
String userName;
// ...
}
现在有一个List<User>对象插入到t_user表里,oracle数据库,mybatis框架,使用批量插入方式。
实现写法不固定,我这样写的,仅作参考
多表插入
<insert id="batchSave" parameterType="com.xuxd.bean.User">
insert all
<foreach collection="list" item="user" separator=" " open=" " close=" " index="index">
into t_user(
user_id,
user_name
) VALUES (
#{user.userId},
#{user.userName}
)
</foreach>
select 1 from dual
</insert>
单表插入
<insert id="batchSave" parameterType="com.xuxd.bean.User">
insert into t_user(user_id, user_name)
select u.id, u.name from
(
<foreach collection="list" index="index" item="user" open=" " close=" " separator=" union all ">
select #{user.userId} as id, #{user.userName} as name from dual
</foreach>
) u
</insert>
说明
这两种写法很常见(细节上可能不同),在网上一搜就出来了,大多类似,对于初学者可能好奇为何这样写,解释下。
下面参考了官方文档,SQL Language Reference11g Release 2 (11.2)
看下插入语法:
单表插入和多表插入,按前面的顺序解释
多表插入
根据当前场景主要是上面红框内,无条件多表插入。
insert all into t1(...) values (...) into t2(...) values(...) ... select ... from t
意思是向t1、t2...等多个表中插入数据,后面注意跟了个子查询select ... from t。这个子查询的结果前面是可以用的。but,重点是这个子查询的结果行数用来计算前面插入的每个表的行数。所以,如果子查询返回多行,前面每个表就会插入多行,对于返回的每一行,每个表都要执行一次插入。如果是0行,前面每个表都不会插入。
因此,当前场景的mybatis写法实现是,插入的多个表都是同一个表,然后select 1 from dual返回的行数是1,每个表就只插入1行。
顺便提一下,如果需要每行id是一个序列生成的,这种情况,就不能这样写了,因为这条语句,会被看做一条sql,所以如果需要生成序列,那么每列的序列值都是同一个值。
单表插入
单表插入,这里实现其实就是一个子查询,查询是借用dual表返回结果,可以看下子查询语法:
每一个子查询:select #{user.userId} as id #{user.userName} as name from dual使用union all,这样就很清楚了。