我需要我的触发器(它在更新表时发送消息)以某种方式运行,如果它是由作业触发的。此作业每小时运行一次,并发送大量消息。有什么办法可以让我做吗。
我试着按照下面的方法来确定invoker是否是一个作业,但似乎不起作用:
select count(1) into nIsJob from V$SESSION x where x.sid in (select t.session_id from all_scheduler_running_jobs t) and x.sid=sys_context('USERENV', 'SID');
整个触发器是这样的:
create or replace trigger tg_spot_in_other_hour
before update
on BREAKS
for each row
declare
vBody VARCHAR2(4000);
nIsJob NUMBER;
begin
select count(1) into nIsJob from V$SESSION x where x.sid in (select t.session_id from all_scheduler_running_jobs t) and x.sid=sys_context('USERENV', 'SID');
if (:new.id_break_types NOT IN (2) or (:new.id_break_types = 5 and nIsJob=0)) and TRUNC(:new.BREAK_TIME / gv.fis / 60 / 60)<>TRUNC(:old.BREAK_TIME / gv.fis / 60 / 60) and (:new.break_date >= sysdate or :old.break_date >= sysdate) then
select 'Break on '||ch.label||' ' into vBody
from channels ch
where ch.id_channels=:new.id_channels;
vBody:=vBody||:new.break_date||' moved from '||pcg_system.num2dur(:old.break_time,'HH:MM')||' to '||pcg_system.num2dur(:new.break_time,'HH:MM');
for x_b in (select c.id_backoffice,c.contract_number,c.label
from spots s, contracts c
where c.id_contracts=s.id_contracts
and s.id_breaks=:new.id_breaks) loop
INSERT INTO messages
(id_users,
header,
message,
created)
values (x_b.id_backoffice,'Spot moved to different hour',vBody||' Contract: '||x_b.contract_number||' ('||x_b.label||')',sysdate) ;
end loop;
end if;
end tg_spot_in_other_hour;
3条答案
按热度按时间h5qlskok1#
您可以通过
DBMS_APPLICATION_INFO
使用上下文来更改触发器的行为。您可以将触发器更改为具有
WHEN
子句,该子句查找上下文值,例如:client_info
:从文档中:
WHEN(条件)
指定数据库为触发语句影响的每一行计算的SQL条件。如果受影响行的condition值为TRUE,则为该行运行 trigger_body;否则,trigger_body 不会为该行运行。无论condition的值如何,触发语句都会运行。
然后在作业运行的过程中,在开始时设置上下文:
你也可以/应该在结束时再次清除它,以防会话保持活动状态并被重用(所以也可能在异常处理程序中):
所以现在当触发事件是由你的作业引起的时候,
WHEN
子句将计算为false,触发器主体将不会被执行;否则,它将评估为true,并且它仍将发送消息。没有什么可以阻止其他人手动设置上下文,但是如果你认为这是可能的,你可以确保使用的值是不寻常的或者不太可能是随机选择的;和/或使用上下文值(信息、模块、动作...)的组合。
使用
SCHEDULER_JOB
,FG_JOB_ID
或BG_JOB_ID
作为@PaulW建议是gong更简单,因为你不需要改变作业的过程来设置自己的东西。我将把它留在这里,因为这在其他情况下可能很有用,比如区分来自应用程序的调用,或者单个与批处理(但不是调度程序!))作业,或在升级期间...jfgube3f2#
有许多方法可以做到这一点。以下是其他几个:
1.查看当前会话的
pname
,看看它是否是一个作业进程:1.或者更简单地,使用
SYS_CONTEXT
值,如SCHEDULER_JOB
,FG_JOB_ID
或BG_JOB_ID
:或
您还可以将
dba_scheduler_jobs.job_name
与v$session.action
字段匹配。有很多选择。nmpmafwu3#
您可以使用
它将返回所有的细节,你可以区分,如果它是由工作或不解雇。
详细信息请参见文档。