在Oracle数据库的实际开发场景中,批量插入多行数据的需求十分常见,传统的逐条执行INSERT语句的方式会产生多次数据库交互,效率较低。通过UNION ALL连接多个SELECT语句作为子查询,配合INSERT语句可以一次性完成多行数据的插入,大幅减少交互次数,提升操作效率。

基础语法结构
利用UNION ALL连接SELECT实现多行INSERT的核心语法如下:
INSERT INTO 目标表名 (列1, 列2, 列3) SELECT 值1, 值2, 值3 FROM DUAL UNION ALL SELECT 值4, 值5, 值6 FROM DUAL UNION ALL SELECT 值7, 值8, 值9 FROM DUAL;
其中DUAL是Oracle的虚拟表,用于构造不包含实际表关联的单行数据。每个SELECT语句对应一行要插入的数据,UNION ALL用于连接多个结果集,保留所有重复行,比UNION效率更高,因为不需要去重。
具体实现示例
示例1:插入固定值多行数据
假设存在用户表user_info,结构如下:
| 列名 | 类型 | 说明 |
|---|---|---|
| user_id | NUMBER | 用户ID |
| user_name | VARCHAR2(50) | 用户名称 |
| age | NUMBER | 用户年龄 |
需要向表中插入3条用户数据,语句如下:
INSERT INTO user_info (user_id, user_name, age) SELECT 1001, '张三', 25 FROM DUAL UNION ALL SELECT 1002, '李四', 28 FROM DUAL UNION ALL SELECT 1003, '王五', 22 FROM DUAL;
执行后可以通过SELECT * FROM user_info;查询验证插入结果,3条数据会一次性写入表中。
示例2:结合其他表数据插入多行
如果需要从已有表temp_user中筛选数据插入到user_info表,也可以结合UNION ALL实现:
INSERT INTO user_info (user_id, user_name, age) SELECT t.user_id, t.user_name, t.age FROM temp_user t WHERE t.status = 1 UNION ALL SELECT 2001, '赵六', 30 FROM DUAL UNION ALL SELECT 2002, '孙七', 27 FROM DUAL;
上述语句会先插入temp_user表中状态为1的用户数据,再插入两条固定值的用户数据,所有数据一次性完成插入。
注意事项
- 每个
SELECT语句返回的列数必须与INSERT语句后的列数一致,且对应列的数据类型要兼容,否则会报数据类型不匹配的错误。 - 优先使用
UNION ALL而不是UNION,因为UNION会对结果集进行去重排序,额外消耗资源,除非明确需要去重,否则不建议使用。 - 如果插入的数据量非常大,比如超过几千行,建议分批次执行插入操作,避免单次SQL语句过长导致解析效率下降或者超出SQL长度限制。
- 插入操作执行后需要手动提交事务,或者使用自动提交配置,否则数据不会持久化到数据库中。
事务提交示例
插入完成后提交事务的语句如下:
COMMIT;
如果需要回滚插入操作,可以执行ROLLBACK;语句,前提是事务还未提交。