Oracle如何实现不存在则插入,选普通SQL还是PL/SQL
实现方案
优先选择纯SQL实现即可,不需要额外编写PL/SQL块,单条语句原子性完成取值、存在性判断、插入全流程,性能更好也能避免多语句执行的并发冲突问题。
推荐写法:MERGE语句
这是Oracle场景下实现「不存在则插入」逻辑的标准高效方案,单语句原子执行,不会出现并发场景下的重复插入问题:
MERGE INTO STATS_CLIENT_TEST t USING ( SELECT codeclient, 9 AS codeaxestat, 1 AS second_num_col, 'UNKNOWN' AS status_name FROM STATS_CLIENT_TEST WHERE CODEAXESTAT = 5 ) s ON ( t.codeclient = s.codeclient AND t.CODEAXESTAT = s.codeaxestat AND t.third_col = s.second_num_col -- 替换为表中第三个数值列的实际列名 AND t.fourth_col = s.status_name -- 替换为表中第四个存储名称的列的实际列名 ) WHEN NOT MATCHED THEN INSERT (codeclient, CODEAXESTAT, third_col, fourth_col) VALUES (s.codeclient, s.codeaxestat, s.second_num_col, s.status_name);
执行前把代码里的
third_col、fourth_col替换成你表中对应第三列、第四列的真实字段名即可。
可选写法:INSERT + NOT EXISTS
如果不习惯用MERGE,也可以用带存在性判断的INSERT SELECT写法,同样是纯SQL实现:
INSERT INTO STATS_CLIENT_TEST (codeclient, CODEAXESTAT, third_col, fourth_col) SELECT src.codeclient, 9, 1, 'UNKNOWN' FROM STATS_CLIENT_TEST src WHERE src.CODEAXESTAT = 5 AND NOT EXISTS ( SELECT 1 FROM STATS_CLIENT_TEST exist WHERE exist.codeclient = src.codeclient AND exist.CODEAXESTAT = 9 AND exist.third_col = 1 AND exist.fourth_col = 'UNKNOWN' );
方案选择说明
- 不推荐先单独执行SELECT查询codeclient值,再手动拼接INSERT语句的写法:这种方式需要至少两次数据库交互,高并发场景下可能出现「查询时记录不存在、插入前其他会话已写入同条记录」的竞态问题,触发唯一约束冲突报错。
- PL/SQL仅适合插入操作后需要额外做分支逻辑(比如插入成功后输出日志、未插入时触发其他业务逻辑)的场景,仅做条件插入的话纯SQL执行效率更高,没有SQL和PL/SQL引擎切换的额外开销。
内容的提问来源于stack exchange,提问作者Abou Ilyès
相关产品推荐
相关产品推荐

