ODI增量MERGE场景下APEX专属Trigger异常及优化问询
解决方案
针对你的问题,这里有几种更简洁的实现方式,无需检查15个列的新旧值差异:
方案一:判断是否为APEX会话触发
利用APEX的会话特性,仅当操作来自APEX平台时才更新跟踪字段。ODI执行时无APEX会话,相关变量为空,以此作为判断依据:
create or replace TRIGGER DW.TRG BEFORE UPDATE ON DW.TABLE REFERENCING NEW AS new OLD AS old FOR EACH ROW BEGIN -- 仅APEX会话下(APP_USER不为空)更新跟踪字段 IF updating AND v('APP_USER') IS NOT NULL THEN :new.changed_on_dt := SYSDATE; :new.changed_by := v('APP_USER'); END IF; END; /
更严谨的方式可检查APEX应用ID:
create or replace TRIGGER DW.TRG BEFORE UPDATE ON DW.TABLE REFERENCING NEW AS new OLD AS old FOR EACH ROW BEGIN IF updating AND v('APP_ID') IS NOT NULL THEN :new.changed_on_dt := SYSDATE; :new.changed_by := v('APP_USER'); END IF; END; /
注:非APEX环境下v('APP_USER')返回NULL,ODI执行时不会触发跟踪字段更新,避免覆盖原有值。
方案二:ODI执行时显式保留跟踪字段值
修改ODI的MERGE语句,在UPDATE部分明确保留changed_on_dt和changed_by的原有值,不进行更新:
MERGE INTO DW.TABLE t USING staging_table s ON (t.id = s.id) WHEN MATCHED THEN UPDATE SET t.col1 = s.col1, t.col2 = s.col2, -- 其他业务列... -- 保留原有跟踪字段值 t.changed_on_dt = t.changed_on_dt, t.changed_by = t.changed_by WHEN NOT MATCHED THEN INSERT (id, col1, col2, changed_on_dt, changed_by) VALUES (s.id, s.col1, s.col2, SYSDATE, 'ODI_SYSTEM'); -- 插入时可设置默认值
这种方式无需修改触发器,直接从ETL层面控制跟踪字段的更新逻辑。
方案三:通过会话上下文标记ODI操作
在ODI执行任务前设置自定义会话变量,触发器检查该变量,若为ODI操作则跳过跟踪字段更新:
- ODI任务开始时执行:
BEGIN DBMS_SESSION.SET_CONTEXT('ETL_CONTEXT', 'IS_ODI', 'Y'); END; /
- 修改触发器:
create or replace TRIGGER DW.TRG BEFORE UPDATE ON DW.TABLE REFERENCING NEW AS new OLD AS old FOR EACH ROW BEGIN -- 非ODI会话时才更新跟踪字段 IF updating AND SYS_CONTEXT('ETL_CONTEXT', 'IS_ODI') IS NULL THEN :new.changed_on_dt := SYSDATE; :new.changed_by := v('APP_USER'); END IF; END; /
- ODI任务结束时可清除上下文(可选):
BEGIN DBMS_SESSION.CLEAR_CONTEXT('ETL_CONTEXT'); END; /
内容的提问来源于stack exchange,提问作者Leverage
相关产品推荐
相关产品推荐

