Un approccio leggermente diverso consiste nel mantenere i trigger abilitati ma ridurne (se non del tutto rimuoverli) l'impatto, aggiungendo un when
clausola qualcosa del tipo:
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;
/
Quindi nella tua procedura aggiungi una chiamata al inizia come passaggio "disabilita i trigger":
dbms_application_info.set_client_info('BATCH');
e cancellalo di nuovo alla fine, nel caso in cui la sessione venga lasciata viva e riutilizzata (quindi potresti volerlo fare anche in un gestore di eccezioni):
dbms_application_info.set_client_info(null);
Puoi anche usare il modulo, l'azione o una combinazione. Mentre questa impostazione è attiva, il trigger verrà comunque valutato ma non si attiverà, quindi qualsiasi cosa che accade all'interno verrà saltata:il corpo del trigger non viene eseguito, poiché i documenti mettilo.
Questo non è infallibile in quanto non c'è nulla che impedisca ad altri utenti/applicazioni di fare le stesse chiamate, ma se scegli una stringa più descrittiva e/o una combinazione di impostazioni, dovrebbe essere deliberata - e penso che tu sia principalmente preoccupato per gli incidenti, non per i cattivi attori.
Test rapido della velocità con un trigger inutile che rallenta un po' le cose.
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);
C'è un po' di variazione rispetto all'effettuare chiamate remote, ma ho eseguito alcune volte ed è chiaro che l'esecuzione con un trigger semplice è molto simile all'esecuzione con il trigger vincolato senza BATCH impostato, ed entrambi sono molto più lenti rispetto all'esecuzione senza trigger o con il trigger vincolato con BATCH impostato. Nei miei test c'è una differenza di ordine di grandezza.