解决SqlServer批量插入最多2100条数据的方法

本文介绍在使用SqlServer时如何通过Java实现高效批量插入和更新数据的方法。通过限制每次操作的数据量来避免超过系统限制,并利用流操作分批处理数据集。同时提供mapper.xml中的SQL语句示例。

SqlServer批量插入数据时最多不能超过2100条,记录一下解决办法
Java代码:

 public void batchInsert(List<Student> list) {
        Integer BATCH_SIZE = 100;
        if (CollectionUtils.isNotEmpty(list)) {
            int insertListSize = list.size();
            int pageNum = insertListSize % BATCH_SIZE == 0 ? insertListSize / BATCH_SIZE : (insertListSize / BATCH_SIZE + 1);
            if (pageNum > 0) {
                for (int i = 1; i <= pageNum; i++) {
                    studentMapper.batchInsert(list.stream().skip(BATCH_SIZE * (i - 1)).limit(BATCH_SIZE).collect(Collectors.toList()));
                }
            }
        }
    }

mapper.xml中的sql语句:

<insert id="batchInsert" parameterType="java.util.List">
        insert into student
        (
	        id,
	        name,
	        del_flag,
	        create_time,    create_by
        )
        values
        <foreach collection="list" item="item" index="index" separator=",">
         (
            #{item.id},
            #{item.name},
            #{item.delFlag},
            #{item.createTime},#{item.createBy}
          )
        </foreach>
    </insert>

顺便记录一下批量更新,与批量插入基本一致
Java代码:

 public void batchUpdate(List<Student> list) {
        final int BATCH_UPDATE_SIZE = 80;
        if (CollectionUtils.isNotEmpty(list)) {
            int updateListSize = list.size();
            int pageNum = updateListSize % BATCH_UPDATE_SIZE == 0 ? updateListSize / BATCH_UPDATE_SIZE : (updateListSize / BATCH_UPDATE_SIZE + 1);
            if (pageNum > 0) {
                for (int i = 1; i <= pageNum; i++) {
                    studentMapper.batchUpdate(list.stream().skip(BATCH_UPDATE_SIZE * (i - 1)).limit(BATCH_UPDATE_SIZE).collect(Collectors.toList()));
                }
            }
        }
    }

mapper.xml中的sql语句:

    <update id="batchUpdate">
        update student
        <trim prefix="set" suffixOverrides=",">

            <trim prefix=" name = case" suffix=" end, ">
                <foreach collection="updateList" item="item" index="index">
                    <if test="item.name != null">
                        when id = #{item.id} then #{item.name}
                    </if>
                </foreach>
            </trim>

            <trim prefix=" del_flag = case" suffix=" end, ">
                <foreach collection="updateList" item="item" index="index">
                    <if test="item.delFlag != null">
                        when id = #{item.id} then #{item.delFlag}
                    </if>
                </foreach>
            </trim>

            <trim prefix=" update_time = case" suffix=" end, ">
                <foreach collection="updateList" item="item" index="index">
                    <if test="item.updateTime != null">
                        when id = #{item.id} then #{item.updateTime}
                    </if>
                </foreach>
            </trim>

            <trim prefix=" update_by = case" suffix=" end, ">
                <foreach collection="updateList" item="item" index="index">
                    <if test="item.updateBy != null">
                        when id = #{item.id} then #{item.updateBy}
                    </if>
                </foreach>
            </trim>
        </trim>
        where id in
        <foreach collection="updateList" index="index" item="item" separator="," open="(" close=")">
            #{item.id}
        </foreach>
    </update>
批量插入操作在单次请求中最多支持插入的记录数,取决于多个因素,包括数据库类型、配置参数以及插入语句的结构。以下是影响单次批量插入记录数的关键因素: - **数据库参数限制**:某些数据库(如 SQL Server)对单 SQL 语句中允许的参数数设置了上限。例如,SQL Server 最多支持 2100 个参数[^2]。如果每记录需要插入 10 个字段,则单次插入的记录最多为 210 。超过此限制将导致错误,因此需要根据字段数动态调整每次插入的记录数。 - **SQL 语句长度限制**:数据库通常对单 SQL 语句的总长度有限制。虽然没有统一的硬性规定,但过长的 SQL 语句可能导致性能下降或执行失败。因此,在实际操作中建议控制每次插入数据,以避免超出数据库的语句长度限制。 - **性能优化建议**:从性能角度来看,一次性插入 20~50 行记录通常可以达到较好的执行效率。如果插入的行数过少,会导致网络往返次数增加;如果插入的行数过多,则可能引起内存占用过高或事务日志膨胀,影响整体性能[^1]。 - **分插入策略**:在处理大数据时,推荐采用分插入的方式。例如,若需插入上万记录,可将数据划分为多个小次,每个插入 200~300 记录,从而避免因单次插入数据过大而导致的性能瓶颈或参数限制问题[^2]。 - **JDBC 批量处理机制**:使用 JDBC 的 `addBatch()` 和 `executeBatch()` 方法进行批量插入时,可以有效减少数据库的提交次数,提高插入效率。这种方式允许将多个插入操作缓存在内存中,最终一次性提交,从而降低事务开销[^4]。 - **文件导入方式**:对于超大规模数据(如千万记录),推荐使用文件导入的方式(如 `LOAD DATA INFILE`)进行插入操作。这种方式绕过逐 SQL 插入限制,直接读取文件内容并批量导入数据库,效率远高于传统 SQL 插入语句[^3]。 ### 示例代码 以下是一个基于 Java批量插入实现示例,使用分次策略控制每次插入数据: ```java int bunchSize = 290; // 根据数据库参数限制计算出的每次插入记录数 if (sapInfoList != null && sapInfoList.size() > 0) { for (int i = 0; i < sapInfoList.size(); i += bunchSize) { int end_dex = Math.min(i + bunchSize, sapInfoList.size()); List<SapSelect> sapInfoSubList = sapInfoList.subList(i, end_dex); this.sapParamMapper.insertBunch(sapInfoSubList); } } ``` ### 结论 单次批量插入操作最多支持的记录数受限于数据库参数、SQL 语句长度、性能优化目标以及插入方式。建议结合实际数据库配置和性能测试结果,选择合适的插入次大小,以实现高效、稳定的批量插入操作。 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值