Oracle SQL 集合操作详解
Oracle SQL 集合操作详解
适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
SQL 集合操作合并结果集[1]:
详细见:Oracle SQL 集合操作。
2. UNION
2.1 UNION
-- 去重
SELECT id, name FROM employees WHERE dept_id = 10
UNION
SELECT id, name FROM employees WHERE dept_id = 20;
2.2 UNION ALL
-- 不去重(推荐)
SELECT id, name FROM employees WHERE dept_id = 10
UNION ALL
SELECT id, name FROM employees WHERE dept_id = 20;
2.3 性能
- UNION ALL:无排序,快
- UNION:排序去重,慢
- 优先 UNION ALL
3. INTERSECT
-- 交集
SELECT id FROM employees WHERE dept_id = 10
INTERSECT
SELECT id FROM employees WHERE salary > 5000;
-- 即 dept_id = 10 AND salary > 5000
4. MINUS
-- 差集
SELECT id FROM employees
MINUS
SELECT id FROM employees WHERE status = 'INACTIVE';
-- 即 status != 'INACTIVE'(含 NULL)
5. 规则
5.1 列数相同
-- 必须列数相同
SELECT id, name FROM t1
UNION
SELECT id, name FROM t2;
5.2 类型兼容
-- 类型兼容
SELECT id, name FROM employees -- NUMBER, VARCHAR2
UNION
SELECT emp_id, emp_name FROM contractors; -- NUMBER, VARCHAR2
5.3 顺序
-- ORDER BY 在最后
SELECT id, name FROM t1
UNION
SELECT id, name FROM t2
ORDER BY id;
5.4 列名
-- 第一个 SELECT 决定列名
SELECT id AS employee_id, name FROM employees
UNION
SELECT emp_id, emp_name FROM contractors
ORDER BY employee_id;
6. 应用场景
6.1 合并
-- 多表合并
SELECT 'EMP' AS type, id, name FROM employees
UNION ALL
SELECT 'CON' AS type, id, name FROM contractors
UNION ALL
SELECT 'VENDOR' AS type, id, name FROM vendors;
6.2 比较
-- 找出在不同表的数据
SELECT id, name FROM employees
MINUS
SELECT id, name FROM employees_backup;
6.3 报表
-- 汇总
SELECT 'IT' AS dept, COUNT(*) AS cnt FROM employees WHERE dept_id = 10
UNION ALL
SELECT 'Sales', COUNT(*) FROM employees WHERE dept_id = 20
UNION ALL
SELECT 'Other', COUNT(*) FROM employees WHERE dept_id NOT IN (10, 20);
6.4 分页
-- 多源分页
SELECT * FROM (
SELECT id, name FROM employees
UNION ALL
SELECT id, name FROM contractors
)
ORDER BY id
OFFSET 100 ROWS FETCH NEXT 10 ROWS ONLY;
7. 替代
7.1 OR
-- UNION ALL 替代 OR
SELECT * FROM employees WHERE id = 1
UNION ALL
SELECT * FROM employees WHERE salary > 10000 AND id != 1;
-- 等效
SELECT * FROM employees WHERE id = 1 OR salary > 10000;
7.2 IN
-- INTERSECT
SELECT id FROM t1
INTERSECT
SELECT id FROM t2;
-- 等效
SELECT id FROM t1 WHERE id IN (SELECT id FROM t2);
7.3 NOT EXISTS
-- MINUS
SELECT id FROM t1
MINUS
SELECT id FROM t2;
-- 等效
SELECT id FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t2.id = t1.id);
详细见:Oracle 子查询与 EXISTS。
8. 性能
8.1 UNION ALL
- 无排序
- 无去重
- 快
8.2 UNION / INTERSECT / MINUS
- 排序去重
- 内存
- 慢
8.3 优化
- 索引
- 减少列
- 限制行
- 替代
9. 复杂示例
9.1 多表
-- 三个表合并
SELECT id, name, 'EMP' AS type FROM employees
UNION ALL
SELECT id, name, 'CON' FROM contractors
UNION ALL
SELECT id, name, 'VENDOR' FROM vendors
ORDER BY type, name;
9.2 聚合
-- 各表统计
SELECT 'EMP' AS type, COUNT(*) AS cnt, SUM(salary) AS total FROM employees
UNION ALL
SELECT 'CON', COUNT(*), SUM(rate) FROM contractors;
9.3 对比
-- 同期对比
SELECT '2024' AS year, dept_id, SUM(amount) AS total FROM sales_2024 GROUP BY dept_id
UNION ALL
SELECT '2025', dept_id, SUM(amount) FROM sales_2025 GROUP BY dept_id
ORDER BY dept_id, year;
10. 12c+ 增强
10.1 MATCH_RECOGNIZE
-- 模式匹配
SELECT *
FROM stock_prices
MATCH_RECOGNIZE (...);
详细见:Oracle SQL 模式匹配。
10.2 FETCH
-- 集合后分页
SELECT ... UNION ...
ORDER BY ...
OFFSET 100 ROWS FETCH NEXT 10 ROWS ONLY;
详细见:Oracle 12c 新 SQL 特性。
11. 常见坑与排错
11.1 列数不匹配
- ORA-01789
- 检查列
11.2 类型不兼容
- ORA-01790
- 转换
11.3 ORDER BY
- 仅最后
- 列名第一个
11.4 NULL
- UNION 视 NULL 相同
- UNION ALL 保留
12. 最佳实践
- UNION ALL 优先:性能
- 列数相同:规则
- 类型兼容:转换
- ORDER BY 最后:语法
- 限制行:性能
- 替代 OR / IN:性能
- 索引:优化
- 测试:验证
- 执行计划:检查
- 文档化:说明
13. 参考资料
[1] Oracle Database SQL Language Reference 19c, “Set Operators” https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SELECT.html