Trochu odlišný přístup je ponechat spouštěče povolené, ale omezit (pokud ne zcela odstranit) jejich dopad přidáním when
klauzule něco jako:
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;
/
Poté ve svém postupu přidejte volání na začít jako krok „zakázat spouštěče“:
dbms_application_info.set_client_info('BATCH');
a na konci ji znovu vymažte, pro případ, že by relace zůstala naživu a znovu použita (takže to možná budete chtít udělat i v obslužném programu výjimky):
dbms_application_info.set_client_info(null);
Můžete také použít modul, akci nebo kombinaci. I když je toto nastavení na místě, spoušť bude stále vyhodnocena, ale nespustí se, takže cokoli, co se děje uvnitř, bude přeskočeno – tělo spouště se nespustí, protože dokumenty dej to.
Není to zcela spolehlivé, protože ve skutečnosti nic nebrání ostatním uživatelům/aplikacím provádět stejná volání, ale pokud zvolíte popisnější řetězec a/nebo kombinaci nastavení, muselo by to být záměrné – a myslím, že většinou strach z nehod, ne špatných herců.
Rychlý test rychlosti se zbytečným spouštěčem, který dělá věci jen trochu zpomaluje.
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);
Od vzdálených hovorů se trochu liší, ale párkrát jsem běžel a je jasné, že běh s obyčejným spouštěčem je velmi podobný běhu s omezeným spouštěčem bez nastaveného BATCH a obojí je mnohem pomalejší než běh bez spouště nebo s omezená spoušť s nastavenou BATCH. V mém testování je řádový rozdíl.