oracle 嗅出已激活触发器的实际请求

sgtfey8w  于 2023-06-29  发布在  Oracle
关注(0)|答案(1)|浏览(93)

我在工作中遇到了一个问题,这个问题已经困扰了服务部门几个星期了。我已经写了一个触发器,试图抓住起源或一个错误。但这就像大海捞针
有没有办法在var中包含DML事务,以便我可以看到激活触发器的实际事务?
就像想象一下:

CREATE OR REPLACE TRIGGER SYSADM.WOW_TRIGGER
AFTER UPDATE
ON SYSADM.TABLE1 REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
WHEN (
NEW.COLUMN1 is null and new.COLUMN2 is not null and NEW.COLUMN in ('A','B')
      )
DECLARE
[...]
V_catch clob;

begin 

[...]
end;

===>如何在V_catch中注册此事务:update table1 set column2 = "WHATEVER" where COLUMN15555 = 1在客户点击软件后发生了什么?
我试着在它上面做一些讨厌的工作,在每一列上写自定义if条件,试图得到改变的值:

if :NEW.column1 is not null then 
v_catch := v_catch || :NEW.column1;
end if;
if :NEW.column2 is not null then 
v_catch := v_catch || :NEW.column2;
end if;

[...]
这实际上并不像我们预期的那样工作,因为我们经常收到bug的通知,在报告中,v_catch返回的是非贵重值,而bug仍然无法定位。
我很确定有一种方法可以做到这一点,但我仍然是一个初学者,在PLSQL和SQL for Oracle中自学。也许我忽略了什么,也许这是唯一存在的方法。有哪位老前辈能帮我解决这个问题吗?

ca1c2owp

ca1c2owp1#

审计绝对是正确的答案。但是,如果您有一个使用审计的限制,那么触发器是您的下一个最佳选择。
问题是,除了DDL/系统事件触发器或细粒度审计(分别可以使用original_sql_txtSYS_CONTEXT('USERENV','CURRENT_SQL'))之外,我认为不可能以干净的方式在DML触发器中获得触发SQL。虽然您认为可以查询v$session.sql_id,但这样做的查询将用它本身替换它。然而,这里有一个可以接近的黑客,通过查看会话打开的游标以及在过去一秒内活动的游标。

create table tmp55 (col1 integer);

create or replace trigger tr_tmp55 after insert or update or delete on tmp55 for each row
begin
  FOR rec_cursor IN (SELECT oc.*,s.sql_fulltext
                       FROM v$open_cursor oc,
                            v$sql s
                      WHERE oc.sid = SYS_CONTEXT('USERENV','SID')
                        AND oc.child_address = s.child_address
                        AND oc.sql_id = s.sql_id
                        AND s.last_active_time >= SYSDATE - 1/86400
                        AND UPPER(sql_fulltext) LIKE '%TMP55%'
                        AND UPPER(sql_fulltext) NOT LIKE '%OPEN_CURSOR%')
  LOOP
    dbms_output.put_line(SUBSTR(rec_cursor.sql_fulltext,1,32676));
  END LOOP; 
end;

它可能返回多行,但其中只有一行是正确的SQL。另外,为了减少结果,假设DML将命名表(而不是通过视图或同义词)。您可能需要更改dbms_output以插入到日志表中沿着提供有用的会话标识信息。显然,这是粗略的,可以调整,但它给出了基本的想法。

相关问题