ORDS批量插入UEM表时复合触发器仅触发1次仅取最后ID问题咨询
触发器异常原因分析
- 触发时机错误:你当前使用的是
AFTER STATEMENT级别的触发逻辑,整个INSERT语句执行完成后只会触发1次,和插入的行数无关,所以只会向SPRINT1表插入1条数据。 - ID获取逻辑错误:你通过
SELECT MAX(ID) FROM UEM取到的是整张表最大的ID值,自然只能拿到本次批量插入的最后一条记录的ID,无法获取所有新插入行的ID。同时这种写法还存在并发风险:如果同一时间有其他会话向UEM表插入数据,取到的MAX(ID)可能不属于当前插入的记录,产生脏数据。
修正方案
使用复合触发器的行级触发节点收集所有新插入行的ID,再在语句级节点批量写入关联表,修正后的触发器代码如下:
CREATE OR REPLACE TRIGGER TEST_TRIGGER5 FOR INSERT ON UEM COMPOUND TRIGGER -- 定义存储新ID的集合类型 TYPE id_list IS TABLE OF UEM.ID%TYPE INDEX BY PLS_INTEGER; new_ids id_list; v_index PLS_INTEGER := 1; -- 行级触发:每插入一行就收集对应ID AFTER EACH ROW IS BEGIN new_ids(v_index) := :NEW.ID; v_index := v_index + 1; END AFTER EACH ROW; -- 语句级触发:批量写入关联表 AFTER STATEMENT IS BEGIN FOR i IN 1..new_ids.COUNT LOOP INSERT INTO SPRINT1 (tenantid, usersessionid, newuser, totalerrorcount, userid) VALUES ('deneme', 'testsessionid', 'yes', new_ids(i), 'asdasfqwqwe'); END LOOP; END AFTER STATEMENT; END TEST_TRIGGER5;
性能优化提示
如果单次插入的行数量极大,可以用FORALL替代FOR循环批量插入,降低上下文切换开销:
FORALL i IN 1..new_ids.COUNT INSERT INTO SPRINT1 (tenantid, usersessionid, newuser, totalerrorcount, userid) VALUES ('deneme', 'testsessionid', 'yes', new_ids(i), 'asdasfqwqwe');
内容的提问来源于stack exchange,提问作者serhatbalik
相关产品推荐
相关产品推荐

