Ann*_*awn 4 oracle triggers plsql stored-procedures
我有一个表(Oracle 11g),其中多个包/存储过程运行DML语句.我想捕获使用触发器在表上发出DML的包/过程名称,并将其记录到日志记录表中.
例如:
包MY_PACK.MY_PROC()发出insert into...表格mytab.我会设计一个触发器,mytab它应该能够捕获发出的包/过程名称insert into..并将此信息存储在另一个表中my_tab_log.
我做了一些搜索并发现$$PLSQL_UNIT并且$$PLSQL_LINE可以指出过程名称,但是如果在触发器中使用这些变量,则将捕获触发器名称而不是发出DML语句的包/过程名称.
喜欢 -
CREATE OR REPLACE TRIGGER my_trg
AFTER INSERT OR UPDATE OR DELETE
ON MY_TAB
FOR EACH ROW
BEGIN
IF INSERTING THEN
insert into my_tab_log values('INSERTED A ROW'
sysdate,
$$PLSQL_UNIT);
END IF;
-- This would capture Trigger name but I would like to capture `MY_PACK.MY_PROC()`
-- which issued the insert statement
...
END;
Run Code Online (Sandbox Code Playgroud)
现在,因为$$ PLSQL_UNIT是一个条件编译指令.在编译/重新编译PL/SQL代码时解决了这个问题.所以不幸的是,触发器中的$$ PLSQL_UNIT只是触发器名称,并在触发器编译时解析.
我也找到了这个程序,owa_util.who_called_me但无法解决我如何使用它来满足我的需求.甚至可以实现我想要的而不需要更改发出DML语句的实际包/存储过程?我无法修改这些程序,这是一个严格的限制,所以这不是一个选项.
$$PLSQL_UNIT 只提供包名称,而不是包中的过程名称.同样如此who_called_me.
owa_util.who_called_me是基于一个不可估量的Kyte先生写的小实用程序.如果您在这里查看他的源代码,您将看到例程从调用堆栈中获取其信息.因此,它提供的信息是:
这些令人沮丧的限制归结为过载:我们可以创建具有相同名称但签名不同的打包过程.因此,当识别哪一段代码正在运行时,"过程名称"对系统并不是特别有用.
无论如何,如果你想要玩who_called_me,它需要四个像这样的参数:
create or replace trigger my_trg
before insert or update on my_tab
for each row
declare
l_owner varchar2(30);
l_name varchar2(30);
l_line pls_integer;
l_type varchar2(30);
begin
owa_util.who_called_me(l_owner,l_name,l_line,l_type);
IF INSERTING THEN
insert into my_tab_log values('INSERTED A ROW'
sysdate,
l_owner||'.'||l_name);
END IF;
end;
/
Run Code Online (Sandbox Code Playgroud)