问题描述
insert into批量插入时报错
Cause: java.sql.SQLException: Column count doesn’t match value count at row 1
这类问题除了 表字段的列数与值的列数不相等外,
还有一个foreach循环写法问题,copy代码久了,就容易被忽略
错误写法
insert into table_name (
column_name
) values
<foreach collection="list" item="i" open="(" separator="," close=")">
(
#{i.value}
)
</foreach>
此时控制台SQL会拼接为
insert into table_name ( column_name ) values (( ? ), ( ? ))
正确写法
insert into table_name (
column_name
) values
<foreach collection="list" item="i" separator=",">
(
#{i.value}
)
</foreach>
则控制台SQL会拼接为
insert into table_name ( column_name ) values ( ? ) , ( ? )
原因分析
mybatis标签之foreach参数说明
collection:要循环的集合,list array map等
index:循环索引;
item:循环时的别名;
open:循环以什么开始;
close:循环以什么结束;
separator:循环内容之间以什么分隔
在批量更新/批量删除等,必须要添加 open="(" close=")"
否则SQL就会变成
update table_name set name = ? where id in ? , ?
在foreach 参数加上 open="(" close=")" 之后
update table_name set name = ? where id in (? , ?)
总结
也就是说批量插入insert into这种,使用mybatis foreach标签时不能添加open="(" close=")",否则SQL会在拼接的时候,多添加了"(" 和 “)”,导致最终列数不一致报错。
而像批量更新循环或者批量删除循环时,SQL写法经常是,
update *** where id in (?,?,?)
delete *** where id in (?,?,?)
像这种就需要添加open="(" close=")",以便告知SQL本次循环的开始和结束标志。
拓展
也可以把一些条件写在 open="(" 里面
比如:
update table_name set column_name = #{value}
<foreach collection="list" item="id" open="where id in(" separator="," close=")">
#{id}
</foreach>
操作结果
update table_name set column_name = ? where id in( ? , ? , ?)