Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Wyłącz wyzwalacze i ponownie włącz wyzwalacze, ale w międzyczasie unikaj zmian w tabeli

Nieco innym podejściem jest pozostawienie włączonych wyzwalaczy, ale zmniejszenie (jeśli nie całkowite usunięcie) ich wpływu, poprzez dodanie when klauzula coś w stylu:

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

Następnie w procedurze dodaj połączenie na start jako krok „wyłącz wyzwalacze”:

dbms_application_info.set_client_info('BATCH');

i wyczyść go ponownie na końcu, na wypadek gdyby sesja pozostała aktywna i ponownie wykorzystana (więc możesz to zrobić również w obsłudze wyjątków):

dbms_application_info.set_client_info(null);

Możesz także użyć modułu, akcji lub kombinacji. Gdy to ustawienie jest włączone, wyzwalacz będzie nadal oceniany, ale nie zostanie uruchomiony, więc wszystko, co dzieje się w środku, zostanie pominięte - ciało wyzwalacza nie zostanie uruchomione, ponieważ dokumentacja połóż to.

Nie jest to niezawodne, ponieważ nic tak naprawdę nie powstrzymuje innych użytkowników/aplikacji przed wykonywaniem tych samych połączeń, ale jeśli wybierzesz bardziej opisowy ciąg i/lub kombinację ustawień, będzie to musiało być celowe – i myślę, że głównie martwi się o wypadki, a nie źli aktorzy.

Szybki test prędkości z bezsensownym wyzwalaczem, który tylko trochę spowalnia.

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

Istnieje pewna różnica w stosunku do wykonywania połączeń zdalnych, ale uruchomiłem kilka razy i jasne jest, że bieganie ze zwykłym wyzwalaczem jest bardzo podobne do uruchamiania z ograniczonym wyzwalaczem bez ustawionego polecenia BATCH, a oba są znacznie wolniejsze niż uruchamianie bez wyzwalacza lub z ograniczony wyzwalacz z ustawionym BATCH. W moich testach jest różnica rzędu wielkości.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kolejność Oracle według różnych

  2. Jak znaleźć wersję komponentów EBS R12?

  3. Oracle - w tym zakresie nie istnieje funkcja o nazwie X

  4. Semantyka procedur/funkcji składowanych Oracle w kontekście transakcyjnym

  5. Pokrycie kodu dla PL/SQL