sql >> Database teknologi >  >> RDS >> Oracle

Deaktiver triggere og genaktiver triggere, men undgå tabelændringer i mellemtiden

En lidt anderledes tilgang er at holde triggerne aktiveret, men reducere (hvis ikke helt fjerne) deres påvirkning ved at tilføje en when klausul noget som:

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;
/

Derefter i din procedure tilføj et opkald på start som dit trin 'deaktiver triggere':

dbms_application_info.set_client_info('BATCH');

og ryd den igen til sidst, bare hvis sessionen bliver efterladt i live og genbrugt (så du måske også ønsker at gøre dette i en undtagelseshandler):

dbms_application_info.set_client_info(null);

Du kan også bruge modul, handling eller en kombination. Mens denne indstilling er på plads, vil triggeren stadig blive evalueret, men den udløses ikke, så enhver ting, der sker indeni, springes over - udløserkroppen kører ikke, da dokumenterne sætte det.

Dette er ikke idiotsikkert, da der ikke rigtig er noget, der forhindrer andre brugere/applikationer i at foretage de samme opkald, men hvis du vælger en mere beskrivende streng og/eller en kombination af indstillinger, skal det være bevidst - og jeg tror, ​​at du for det meste bekymret for ulykker ikke dårlige skuespillere.

Hurtig hastighedstest med en meningsløs trigger, der bare bremser tingene en smule.

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);

Der er lidt variation fra at foretage fjernopkald, men jeg løb et par gange, og det er tydeligt, at løb med en almindelig trigger er meget lig med at køre med den begrænsede trigger uden BATCH-sæt, og begge dele er meget langsommere end at køre uden en trigger eller med den begrænsede udløser med BATCH indstillet. I min test er der en størrelsesordensforskel.




  1. ClassNotFoundException:oracle.jdbc.OracleDriver

  2. Simple SQL Server-funktioner til at løse problemer i den virkelige verden

  3. PDO og caching, hvordan implementeres det i en databaseklasse?

  4. Forkert nøglefil til tabel MYSQL