Pendekatan yang sedikit berbeda adalah dengan tetap mengaktifkan pemicu tetapi mengurangi (jika tidak sepenuhnya menghilangkan) dampaknya, dengan menambahkan when
klausa seperti:
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;
/
Kemudian dalam prosedur Anda tambahkan panggilan di mulai sebagai langkah 'nonaktifkan pemicu' Anda:
dbms_application_info.set_client_info('BATCH');
dan hapus lagi di akhir, untuk berjaga-jaga jika sesi dibiarkan hidup dan digunakan kembali (jadi Anda mungkin ingin melakukan ini juga dalam penangan pengecualian):
dbms_application_info.set_client_info(null);
Anda juga bisa menggunakan modul, atau tindakan, atau kombinasi. Saat pengaturan itu ada, pemicu masih akan dievaluasi tetapi tidak akan menyala, jadi apa pun yang terjadi di dalam akan dilewati - badan pemicu tidak berjalan, karena dokumen letakkan.
Ini tidak mudah karena tidak ada yang benar-benar menghentikan pengguna/aplikasi lain melakukan panggilan yang sama, tetapi jika Anda memilih string yang lebih deskriptif dan/atau kombinasi pengaturan, itu harus disengaja - dan saya pikir Anda kebanyakan khawatir tentang kecelakaan bukan aktor yang buruk.
Tes kecepatan cepat dengan pemicu sia-sia yang hanya memperlambat segalanya.
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);
Ada sedikit variasi dari melakukan panggilan jarak jauh, tetapi saya berlari beberapa kali dan jelas bahwa berjalan dengan pemicu biasa sangat mirip dengan berlari dengan pemicu terbatas tanpa set BATCH, dan keduanya jauh lebih lambat daripada berjalan tanpa pemicu atau dengan pemicu yang dibatasi dengan set BATCH. Dalam pengujian saya, ada perbedaan urutan besarnya.