sql >> Databáze >  >> RDS >> Oracle

Zakažte spouštěče a znovu je povolte, ale mezitím se vyhněte změnám v tabulce

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.




  1. SQL Server verze ADD_MONTHS() Oracle

  2. Rychlý kurz ladění výkonu Oracle PL/SQL

  3. jak použít funkci mysql now() v cakephp pro datová pole?

  4. Mysql protínají výsledky