Sunteți pe pagina 1din 6

Facultatea de Cibernetic, Statistic i Informatic Economic

SGBD Oracle seminarul 10

Triggeri pe baza de date


Sunt asociati cu o tabela, view, schema sau database
Sunt stocai n baza de date
Se execut cnd are loc un eveniment. Tipuri de evenimente:
operatii LMD pe o tabela (insert/ update/ delete)
operatii LMD pe o tabela virtuala (view) cu clauza INSTEAD OF
operatii LDD (Create, Alter, Drop) la nivel de database sau schema
evenimente la nivelul schemei sau bazei de date (shutdown sau logon/off)
Se folosesc pentru gestionarea restriciilor de integritate complexe, monitorizare, centralizarea

operatiilor. Nu se recomanda construirea in exces a triggerilor.


Pentru fiecare trigger se stabilete:
comanda care-l declaneaz (insert| update| delete) - Un trigger poate fi declanat de mai
multe comenzi
momentul de timp la care se declaneaz (before| after| instead of). Pentru view se
utilizeaza instead of, actiunile DML vor fi inlocuite de corpul triggerului si vor fi afectate
tabelele din care este construit view-ul.
nivelul (row| statement) - dac triggerul este la nivel de rnd se execut pentru fiecare rnd
afectat de comenzile: insert| update| delete. Daca nu este afectat nici un rand triggerul nu se
executa.
Dimensiunea unui trigger nu poate depasi 32 kb! Se poate include apelul unei proceduri in corpul
triggerului pentru a micsora dimensiunea acestuia.
Pentru a vedea erorile la compilare:
SHOW ERRORS TRIGGER nume_trigger;
Sintaxa de creare a unui trigger:

CREATE [OR REPLACE] TRIGGER nume_trigger


[BEFORE| AFTER| INSTEAD OF]
[INSERT| [OR] | UPDATE [OF coloana,]| [OR] | DELETE]
ON tabela
[FOR EACH ROW ]
[WHEN conditie]
corp_trigger
Corp_trigger poate fi un bloc PL/SQL (BeginEnd) sau un apel de procedura. Procedura poate fi
implementata in PL/SQL, C sau JAVA, iar apelul se realizeaza: CALL nume_proc (fara ; dupa
numele sau!!!)
Exemplu:
--Se creeaz un trigger care se declaneaz naintea fiecrei operaii de inserare n tabela
PRODUSE.
CREATE OR REPLACE TRIGGER produse_trig
BEFORE INSERT ON produse

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle seminarul 10

BEGIN
dbms_output.put_line('triggerul s-a executat');
END;
/
Clauzele INSERTING, UPDATING, DELETING
Exemplu:
Triggerul se declaneaz la operaiile de INSERT, DELETE sau UPDATE pe tabela Produse.
In tabela TEMP_LOG se introduce tipul operaiei, utilizatorul care a executat-o, data
curent.
CREATE TABLE temp_log
(tip CHAR(1),
utilizator VARCHAR2(50),
data DATE DEFAULT SYSDATE);
CREATE OR REPLACE TRIGGER produse_trig_log
BEFORE INSERT or UPDATE or DELETE on produse
DECLARE
v_tip temp_log.tip%TYPE;
BEGIN
case
when INSERTING then v_tip :='I';
when UPDATING then v_tip:='U';
ELSE v_tip :='D';
END case;
INSERT INTO temp_log(tip, utilizator, data) VALUES (v_tip, user, sysdate);
END;
/
Verificarea execuiei:
--inserarea in tabela
insert into produse (id_produs, denumire_produs) values (300, 'cafea');
--stergere
delete from produse where id_produs=300;
commit;
Select * from temp_log;
Triggeri la nivel de rand FOR EACH ROW
In triggerul la nivel de rnd se poate accesa rndul curent procesat folosind doua pseudo-records (
:old, :new). Tipul lor este:
nume_tabela_pe_care_actioneaza_triggerul%ROWTYPE
Valorile pentru :old si :new
Operatie
Valoare pt Old
Valoare pt New
INSERT
NULL
valoarea noua, inserata
2

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle seminarul 10

UPDATE
DELETE

valoare veche, anterioara lui valoare noua, modificata


update
valoare veche, anterioara lui NULL
delete

(:OLD) nu este definit pentru INSERT i (:NEW) nu e definit pentru DELETE


Dei sintactic sunt tratate ca tip de dat record, n realitate ele nu sunt i operaiile de atribuire

directa var_record:=:old ce sunt valide pentru record nu sunt valide pentru (:new) i (:old). Din
acest motiv trebuie precizate exact campurile din pseudo-record :old.camp sau :new.camp.
Nu se recomanda realizarea de triggeri la nivel de rind care utilizeaza valori ale coloanelor din
tabele si care sunt supuse actualizarilor prin comenzile DML ce declanseaza triggerul (mutating
table). Va apare aceeasi eroare ca la functii.
Utilizarea clauzei WHEN pentru a conditiona executia unui trigger:
clauza [when condiie] este valid pentru triggerii la nivel de rnd
corpul triggerului va fi executat numai pentru acele rnduri ce indeplinesc condiia
specificat
Exemple:
--Se creeaz un trigger pentru a nu se permite depirea unei limite maxime a salariului unui
angajat
CREATE OR REPLACE TRIGGER restrict_salariul
BEFORE INSERT or UPDATE on angajati
FOR EACH ROW
DECLARE
v_sal_max number;
BEGIN
select salariu_max into v_sal_max from functii where id_functie= :new.id_functie;
IF :new.salariul>v_sal_max then
RAISE_APPLICATION_ERROR (-20202, 'Nu se poate depasi salariul maxim
pentru functia data');
end if;
END;
/
Verificare execuie se declaneaz triggerul i va apare excepia definit de utilizator.
update angajati
set salariul =15000
where id_angajat=104;
--Se creeaz un trigger care asigur unicitatea codului produsului folosind valorile generate de o
secven
CREATE SEQUENCE produse_secv
START WITH 1
INCREMENT BY 1
MAXVALUE 100
NOCYCLE;
CREATE OR REPLACE TRIGGER generare_codprodus
3

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle seminarul 10

BEFORE INSERT ON produse


FOR EACH ROW
BEGIN
SELECT produse_secv.nextval INTO :new.id_produs FROM dual;
END;
/
show errors;
Clauza INSTEAD OF
Sunt triggeri realizati doar pentru view-uri
Se utilizeaza pentru actualizarea tabelelor din care este construit un view neactualizabil.
Realizeaza operatii DML pe aceste tabele, iar Oracle Server declanseaza triggerii pe tabelele
respective.
Daca un view este actualizabil, triggerii respectivi se declanseaza automat.
Sunt triggeri la nivel de rand.
Nu permit utilizarea clauzelor BEFORE|AFTER
--crearea tabelei virtuale
create or replace view clienti_v as
select cl.id_client, cl.prenume_client, cl.nume_client, cl.limita_credit,co.nr_comanda,
co.data
from clienti cl, comenzi co
where cl.id_client=co.id_client;
--crearea triggerului
create or replace trigger exemplu_trigger
instead of insert or update or delete on clienti_v
for each row
begin
if inserting then
insert into clienti (id_client, prenume_client, nume_client, limita_credit) values
(:new.id_client, :new.prenume_client, :new.nume_client, :new.limita_credit);
insert into comenzi (nr_comanda, data, id_client) values (:new.nr_comanda, :new.data,
:new.id_client);
elsif deleting then
delete from comenzi where nr_comanda=:old.nr_comanda;
elsif updating ('nume_client') then
update clienti
set nume_client=:new.nume_client
where id_client=:old.id_client;
elsif updating ('data') then
update comenzi
set data=:new.data
where nr_comanda=:old.nr_comanda;
end if;
4

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle seminarul 10

end;
/
show errors;
--testare trigger
insert into clienti_v values (10,'Ioan','Bucur',200,100,sysdate);
insert into clienti_v values (20,'Dana','Popa',250,110,sysdate);
select * from clienti where id_client in (10, 20);
select * from comenzi where id_client in (10, 20);
delete from clienti_v where nume_client='Bucur';
select * from clienti where id_client in (10, 20);
select * from comenzi where id_client in (10, 20);
update clienti_v
set nume_client='Popescu'
where id_client=20;
select * from clienti where id_client in (10, 20);
Comparatie intre triggeri si proceduri
Trigger
codul sursa: USER_TRIGGERS
Sunt declansati implicit de DML
Nu sunt permise comenzile: COMMIT,
ROLLBACK, SAVEPOINT, insa pot
contine un apel de procedura in care apar
aceste comenzi, dar nu se recomanda

Procedure
codul sursa: USER_SOURCE
Sunt apelate in mod explicit
Sunt permise comenzile: COMMIT,
ROLLBACK, SAVEPOINT

cnd un trigger e creat, codul surs al triggerului este stocat n dicionarul de date in

user_triggers si se poate afisa:


SELECT trigger_type, trigger_name, triggering_event
FROM user_triggers
WHERE table_name='PRODUSE';
Gestiunea triggerilor:
Un trigger poate fi dezactivat

ALTER TRIGGER nume_trigger DISABLE|ENABLE;


Sau:
ALTER TABLE nume_tabela
DISABLE|ENABLE ALL TRIGGERS;
Exemplu:
ALTER TABLE produse
ENABLE ALL TRIGGERS;
Recompilarea unui trigger se realizeaza prin:

ALTER TRIGGER nume_trigger COMPILE;


5

Facultatea de Cibernetic, Statistic i Informatic Economic


SGBD Oracle seminarul 10

Un trigger se terge cu:

DROP TRIGGER nume_trigger;


Observatie: In momentul stergerii unei tabele se sterg automat toti triggerii asociati acelei tabele.
PL/SQL stocheaz triggerii n forma compilat la fel ca procedurile, funciile i pachetele. Aceasta
permite triggerilor s fie apelai fr recompilare.