Oracle批量插入

mybatis使用foreach批次插入,解决sequence只查询一次的问题

oracle的批量插入方式是: 

insert  into db(id, zgbh, shbzh) 
        select '1', '2', '3' from dual 
        union all select '2', '3', '4' from dual 
        union all select '3', '4', '5' from dual 
        union all select '4', '5', '6' from dual 
        union all select '5', '6', '7' from dual 

 

成功代码如下:

<insert id="batchInsert" parameterType="java.util.List">
	INSERT INTO T_SYS_RESOURCE (RES_ID,RES_CODE,RES_NAME,REMARK,RES_TYPE_ID,INIT_FLAG)
	SELECT SEQ_SYS_RESOURCE.NEXTVAL,A.RES_CODE,A.RES_NAME,A.REMARK,A.RES_TYPE_ID,A.INIT_FLAG FROM( 
    	<foreach collection="list" item="item" index="index" separator="UNION ALL" >
        	SELECT #{item.resCode} RES_CODE,#{item.resName} RES_NAME,#{item.remark} REMARK,
        	#{item.resType.resTypeId} RES_TYPE_ID,#{item.initFlag} INIT_FLAG FROM DUAL 
    	</foreach>
    	) A
</insert>

 foreach拼出来的数据作为一张表A,然后从表A中查询数据,再接上从sequence中读取的值作为id。这样sequence的值就会多次读取,id就会不一样。

<think>我们正在讨论Oracle数据库中的批量插入操作。根据提供的引用,我们可以总结几种常见的批量插入方法: 1. **使用PL/SQL循环**:如引用[1]所示,通过DECLARE块和循环执行动态SQL来创建表(虽然这是复制表结构,但类似方法可用于插入数据)。对于批量插入,可以循环执行INSERT语句。 2. **使用JDBC批处理**:引用[3]展示了使用JDBC的`PreparedStatement`的`addBatch()`和`executeBatch()`方法,这可以减少与数据库的交互次数,提高性能。 3. **使用MyBatis的批量插入**:引用[4]展示了MyBatis框架下使用`foreach`标签构建批量插入SQL。注意,Oracle批量插入的SQL语法与MySQL不同,通常使用`UNION ALL`来合并多个SELECT子句。 4. **使用MERGE语句(UPSERT操作)**:引用[3]中的示例使用了`MERGE`语句,它可以同时处理插入和更新(即如果存在则更新,不存在则插入)。这在需要批量插入并可能更新重复数据时非常有用。 现在,针对用户的问题“我想在Oracle数据库中执行批量插入操作 请问Oracle 批量插入数据 方法”,我们可以提供以下几种方法: ### 方法1:使用INSERT ALL语句(适合少量数据) ```sql INSERT ALL INTO table_name (column1, column2) VALUES (val1, val2) INTO table_name (column1, column2) VALUES (val3, val4) ... SELECT * FROM dual; ``` ### 方法2:使用UNION ALL(适合中等数量数据,但注意SQL长度限制) ```sql INSERT INTO table_name (column1, column2) SELECT val1, val2 FROM dual UNION ALL SELECT val3, val4 FROM dual UNION ALL ...; ``` ### 方法3:使用PL/SQL批量绑定(FORALL) 在PL/SQL块中,使用FORALL可以高效地批量插入。 ```plsql DECLARE TYPE t_tab IS TABLE OF table_name%ROWTYPE; l_tab t_tab := t_tab(); -- 初始化集合 BEGIN -- 填充集合(这里假设有1000条记录) FOR i IN 1..1000 LOOP l_tab.extend; l_tab(l_tab.last).column1 := ...; l_tab(l_tab.last).column2 := ...; END LOOP; -- 批量插入 FORALL i IN 1..l_tab.count INSERT INTO table_name VALUES l_tab(i); COMMIT; END; / ``` ### 方法4:使用外部表 Oracle允许创建外部表,将数据文件(如CSV)映射为数据库表,然后通过INSERT INTO ... SELECT从外部表插入数据。 ### 方法5:使用SQL*Loader工具 Oracle提供的命令行工具,专门用于从文件批量加载数据到数据库。 ### 方法6:使用JDBC批处理(Java程序) 如引用[3]所示,使用JDBC的批处理机制。 ### 方法7:使用MyBatis(Java持久层框架) 如引用[4]所示,在MyBatis映射文件中使用`<foreach>`标签构建批量插入SQL。 **注意事项**: - 当数据量非常大时,建议使用SQL*Loader或外部表。 - 使用JDBC批处理时,注意设置合理的批处理大小(如每1000条执行一次)以避免内存溢出。 - 在MyBatis中使用`UNION ALL`方式时,注意SQL语句长度限制,可以分段执行。 §§相关问题§§ 1. 批量插入时如何避免重复数据? 2. Oracle批量插入的性能优化有哪些方法? 3. 使用MyBatis批量插入时遇到“SQL语句过长”错误怎么办? 4. 如何监控和调整Oracle批量插入操作的性能?</think>### Oracle 批量插入数据方法详解 在Oracle中执行批量插入操作主要有以下几种高效方法,根据实际场景选择合适方案: #### 1. **JDBC批处理(推荐)** ```java Connection conn = DriverManager.getConnection(url, user, pwd); conn.setAutoCommit(false); // 关闭自动提交 PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO employees(id, name, dept) VALUES (?, ?, ?)" ); for (Employee emp : empList) { pstmt.setInt(1, emp.getId()); pstmt.setString(2, emp.getName()); pstmt.setString(3, emp.getDept()); pstmt.addBatch(); // 添加到批处理 } int[] results = pstmt.executeBatch(); // 批量执行 conn.commit(); // 手动提交 ``` **优点**:减少网络往返次数,事务统一管理 **适用**:Java应用程序场景[^3] #### 2. **UNION ALL + SELECT(纯SQL)** ```sql INSERT INTO employees(id, name, dept) SELECT 101, '张三', '技术部' FROM dual UNION ALL SELECT 102, '李四', '市场部' FROM dual UNION ALL SELECT 103, '王五', '财务部' FROM dual; ``` **优点**:单条SQL完成插入 **注意**:数据量过大时可能超出SQL长度限制[^4] #### 3. **PL/SQL批量绑定(FORALL)** ```sql DECLARE TYPE emp_tab IS TABLE OF employees%ROWTYPE; v_emps emp_tab := emp_tab(); BEGIN v_emps.extend(3); v_emps(1) := (101, '张三', '技术部'); v_emps(2) := (102, '李四', '市场部'); v_emps(3) := (103, '王五', '财务部'); FORALL i IN 1..v_emps.count INSERT INTO employees VALUES v_emps(i); COMMIT; END; / ``` **优点**:极致性能,减少上下文切换 **适用**:存储过程或脚本环境[^1] #### 4. **MERGE语句(UPSERT操作)** ```sql MERGE INTO employees t USING ( SELECT 101 AS id, '张三' AS name, '技术部' AS dept FROM dual UNION ALL SELECT 102, '李四', '市场部' FROM dual ) s ON (t.id = s.id) WHEN NOT MATCHED THEN INSERT (id, name, dept) VALUES (s.id, s.name, s.dept); ``` **优点**:支持存在则更新/不存在则插入 **适用**:需要处理重复数据的场景[^3] #### 5. **SQL*Loader(超大数据量)** ```bash sqlldr userid=scott/tiger control=load.ctl ``` 控制文件 `load.ctl` 内容: ```bash LOAD DATA INFILE 'data.csv' APPEND INTO TABLE employees FIELDS TERMINATED BY "," (id, name, dept) ``` **优点**:百万级数据导入首选方案 **性能**:比常规INSERT快10-100倍 --- ### 性能优化建议 1. **批处理大小**:JDBC批处理每1000-5000条提交一次 2. **索引处理**:大数据量导入前禁用索引,完成后再重建 3. **日志精简**:使用`/*+ APPEND */`提示减少重做日志 ```sql INSERT /*+ APPEND */ INTO employees... ``` 4. **错误处理**:使用`LOG ERRORS`子句跳过错误行 ```sql INSERT INTO employees... LOG ERRORS REJECT LIMIT UNLIMITED ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值