Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Nonaktifkan pemicu dan aktifkan kembali pemicu tetapi hindari perubahan tabel untuk sementara

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle.DataAccess.Client.OracleException ORA-03135:koneksi kehilangan kontak

  2. Apakah ada cara untuk memaksa Oracle mengubah rencana kueri tanpa menggunakan petunjuk?

  3. Selesaikan Fungsi Matematika PL/SQL

  4. Kesalahan basis data Oracle di symfony2 (doktrin). Apakah pengaturan parameter.yml dengan benar?

  5. Oracle - Ubah nilai dari baris menjadi rentang