Oracle PL/SQL插入数据前如何校验多字段匹配记录是否存在
PL/SQL多字段校验插入实现
你原有的代码是对str变量拆分得到VALUES集合,对固定的Name字符串拆分得到NAME集合,两个集合做笛卡尔积后写入表,要加NAME+VALUES双字段重复校验,直接替换循环内的插入语句即可,两种常用场景的实现如下:
方案1:重复记录直接跳过(不插入)
使用MERGE INTO实现,多字段匹配逻辑直接写在ON子句中,原子操作不会出现并发重复插入问题,和你原有插入逻辑生成的数据完全一致。
完整修改后代码:
set serveroutput on DECLARE str VARCHAR2(100) := '1,2'; BEGIN FOR i IN ( SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) l FROM dual CONNECT BY LEVEL <= regexp_count(str, ',')+1 ) LOOP -- 替换原INSERT语句为MERGE逻辑 MERGE INTO TBL_TEST_CUSTOMER t USING ( SELECT regexp_substr('Name:check values,Name:bv,Name:cv', '(Name:)?(.*?)(,Name:|$)', 1, level, NULL,2) AS CatName, i.l AS val FROM dual CONNECT BY level <= regexp_count('Name:check values,Name:bv,Name:cv', 'Name:') ) s -- 双字段匹配规则:NAME、VALUES同时相等判定为已存在 ON (t.NAME = s.CatName AND t.VALUES = s.val) WHEN NOT MATCHED THEN INSERT (NAME, VALUES) VALUES (s.CatName, s.val); END LOOP; END; /
方案2:重复记录执行更新
如果匹配到已存在记录时需要同步更新字段(比如更新时间、操作标记等),只需要在MERGE语句中增加WHEN MATCHED分支即可,示例:
MERGE INTO TBL_TEST_CUSTOMER t USING ( SELECT regexp_substr('Name:check values,Name:bv,Name:cv', '(Name:)?(.*?)(,Name:|$)', 1, level, NULL,2) AS CatName, i.l AS val FROM dual CONNECT BY level <= regexp_count('Name:check values,Name:bv,Name:cv', 'Name:') ) s ON (t.NAME = s.CatName AND t.VALUES = s.val) WHEN MATCHED THEN -- 按需写更新逻辑,比如更新最后修改时间 UPDATE SET t.UPDATE_TIME = SYSDATE WHEN NOT MATCHED THEN INSERT (NAME, VALUES) VALUES (s.CatName, s.val);
补充说明
- 不推荐先
SELECT COUNT(*)判断存在性再插入的写法,该写法非原子操作,高并发场景下仍然可能出现重复插入问题,执行效率也低于MERGE - 如果你的表已经给
NAME、VALUES字段建了联合唯一索引,即使不用MERGE,也可以通过捕获DUP_VAL_ON_INDEX异常实现跳过,但代码整洁度和效率都不如MERGE方案
内容的提问来源于stack exchange,提问作者atc
相关产品推荐
相关产品推荐

