更新时间:2023-02-03 20:05:27
一种稍有不同的方法是通过添加when
子句,使触发器保持启用状态,但减小(如果不是完全消除)其影响,请执行以下操作:
A slightly different approach is to keep the triggers enabled but reduce (if not quite entirely remove) their impact, by adding a when
clause something like:
create or replace trigger ...
...
for each row
when (sys_context('userenv', 'client_info') is null
or sys_context('userenv', 'client_info') != 'BATCH')
declare
...
begin
...
end;
/
然后在您的过程中添加呼叫一开始作为禁用触发器"步骤:
Then in your procedure add a call at the start as your 'disable triggers' step:
dbms_application_info.set_client_info('BATCH');
并在最后将其清除,以防万一会话保持活动状态并被重用(因此,您可能也想在异常处理程序中执行此操作):
and clear it again at the end, just in case the session is left alive and reused (so you might want to do this in an exception handler too):
dbms_application_info.set_client_info(null);
您还可以使用模块,操作或组合.设置到位后,触发器仍将被评估但不会触发,因此内部发生的任何事情都将被跳过-触发器主体不运行,如
You could also use module, or action, or a combination. While that setting is in place the trigger will still be evaluated but won't fire, so any thing happening inside will skipped - the trigger body does not run, as the docs put it.
这并不是万无一失的,因为没有什么可以真正阻止其他用户/应用程序进行相同的调用,但是,如果您选择更具描述性的字符串和/或设置的组合,则必须进行仔细考虑-我想您大多是担心事故而不是坏演员.
This isn't foolproof as there is nothing really stopping other users/applications making the same calls, but if you pick a more descriptive string and/or a combination of settings, it would have to be deliberate - and I think you're mostly worried about accidents not bad actors.
使用无意义的触发器进行快速速度测试,只会使事情放慢一点.
Quick speed test with a pointless trigger that does just slows things down a bit.
create table t42 (id number);
-- no trigger
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.050
create or replace trigger tr42 before insert on t42 for each row
declare
dt date;
begin
select sysdate into dt from dual;
end;
/
-- plain trigger
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.466
create or replace trigger tr42 before insert on t42 for each row
when (sys_context('userenv', 'client_info') is null
or sys_context('userenv', 'client_info') != 'BATCH')
declare
dt date;
begin
select sysdate into dt from dual;
end;
/
-- userenv trigger, not set
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.460
- userenv trigger, set to BATCH
exec dbms_application_info.set_client_info('BATCH');
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.040
exec dbms_application_info.set_client_info(null);
进行远程调用有一些差异,但我跑了几次,很明显,使用普通触发器运行与不设置BATCH的受限触发器运行非常相似,并且两者都比不使用BATCH进行运行要慢得多触发或设置了BATCH的约束触发.在我的测试中,存在一个数量级的差异.
There's a bit of variation from making remote calls, but I ran a few times and it's clear that running with a plain trigger is very similar to running with the constrained trigger without BATCH set, and both are much slower than running without a trigger or with the constrained trigger with BATCH set. In my testing there's an order of magnitude difference.