Documente Academic
Documente Profesional
Documente Cultură
Tema:
A examinat lectorul:
Popa Ludmila.
<<Chişinău-2007>>
Cuprins:
Introducere………………………………………………………….................................3
Capitolul I
1. Noţiuni generale despre
Triggere.....................................................................4
1.1 Importanţa şi avantajele utilizării triggerelor....................................................4
1.2 Triggerele şi performanţa.................................................................................5
2. Crearea unui Declanşator. Insrtucţiunea „Create
Trigger”.............................................................................................................7
Exemple:
A. Folosirea unui trigger ca un mesaj.........................................................7
B. Folosirea rezoluţiei numelui întîrziat.....................................................8
C. Folosirea Columns_Update..................................................................10
2.1 Reguli de creare a unui trigger.........................................................................11
2.2 Redenumirea triggerilor...................................................................................11
2.3 Vizualizarea şu testarea unui
trigger..............................................................................14
2.4 Ştergerea unui trigger.......................................................................................14
3. Triggere
multiple................................................................................................15
4. Programarea
triggerelor......................................................................................16
A.Criptarea definiţiilor triggerelor..............................................................16
B. Instrucţiunea SET...................................................................................17
C.Testări pentru modificările coloanelor specificate..................................17
D. Întîrzierea rezoluţiei numelui.................................................................18
E. Returnarea rezultatelor...........................................................................18
5. Triggere ROLLBACK
TRANSACTION...........................................................18
5.1 Folosirea tabelelor speciale Inserted şi Deleted...............................................19
6. Consideraţii
multilinie........................................................................................19
7. Triggere de insert
condiţionat.............................................................................21
8. Valori NULL implicite şi
explicite.....................................................................23
9. Triggere
încuibărite.............................................................................................24
2
3
Introducere.
În ultimele decenii se observă dezvoltarea pe scară largă a Sistemelor
Informatice şi Tehnologiilor de Programare care au devenit în prezent
principalele surse rapide de informaţii şi de operaţionalizare a datelor. În zilele
noastre un număr crescînd de clienţi doresc din ce în ce mai multe informaţii. În
unele domenii există cerinţe de realizarea rapoartelor lunare, trimestriale
detaliate şi a multor altele. De aceia pentru a satisface aceste necesităţi
organizaţionale ne sunt utile Bazele de Date proiectate care stochează şi
afişează datele corespunzătoare. Un limbaj foarte important în gestiunea bazelor
de date relaţionale îl constituie limbajul SQL. Sistemul de Gestiune MS SQL
Server întreţine posibilitatea de prelucrare a datelor în reţea, de a asigura
accesul aplicaţiior la baza de date utilizînd nucleul SQL Server. Acest sistem
garantează integritatea, administrarea şi securitatea datelor. De asemenea el ne
permite să aplicăm o gamă largă de operatori, instrucţiuni, funcţii şi proceduri
care ne ajută la manipularea datelor. Un tip de procedură stocată ce ne permite
ghidarea datelor sunt Declanşatoarele sau Triggerele. Acestea reprezintă nişte
proceduri memorate strîns legate de careva evenimente din baza de date care
duc la modificarea de stare a bazei de date şi care verifică diferite restricţii
impuse de baza de date.
În acest proiect voi desfăşura activitatea, importanţa şi avantajele
utilizării Triggerilor. La rîndul său voi defini noţiunile de bază legate de această
procedură. Utilizînd baza de date „Complex Sportiv”, voi aplica cunoştinţele
mele asupra ei, efectuînd diferite operaţii şi exerciţii cu triggere care se
îndeplinesc în mod automat la apariţia evenimentului de care este asociat.
Triggerul se îndeplineşte independent de modul în care a apărut evenimentul şi
menţine în mod automat integritatea bazei de date. Deci scopul meu este de a
vedea toate situaţiile posibile de creare şi executare a triggerilor care vor
gestiona baza de dată creată.
4
Capitolul I
5
exemplu, cînd se crează un trigger de inserare pe
antrenor.id_antrenor acesta rollback o inserează daca noua valoare nu
se potriveste cu careva valori in echipa.id_antrenor.
Triggerele pot forta restrictii care sunt mai complexe decît cele definite
de constrîngerile CHECK.
Spre deosebire de constrîngerile CHECK, triggerele pot indica coloane
in alte tabele. De exemplu, un trigger poate folosi un SELECT din alt
tabel pentru a face rollback modificările care încearcă sa crească un
preţ al carţii mai mult decît un procent.
Triggerele pot de asemenea sa gasească diferenţe intre starea unei
tabele înainte si după o modificare de date si acţionează bazîndu-se pe
aceste diferenţe.
Triggerele multiple de acelaşi tip (INSERT, UPDATE sau DELETE)
pe o tabela permit ca multiple acţiuni diferite sa aibă loc ca răspuns la
aceleaşi instrucţiuni modificate.
6
Sintaxa
CREATE TRIGGER trigger_name
ON table
[WITH ENCRYPTION]
{
{FOR { [DELETE] [,] [INSERT] [,] [UPDATE] }
[WITH APPEND]
[NOT FOR REPLICATION]
AS
sql_statement [...n]
}
|
{FOR { [INSERT] [,] [UPDATE] }
[WITH APPEND]
[NOT FOR REPLICATION]
AS
{ IF UPDATE (column)
[{AND | OR} UPDATE (column)]
[...n]
| IF (COLUMNS_UPDATED() {bitwise_operator}
updated_bitmask)
{ comparison_operator} column_bitmask
[...n]
}
sql_statement [ ...n]
}
}
Argumente
trigger_name
Este numele triggerului. Numele unui trigger trebuie sa fie conform
regulilor pentru identificatori si trebuie sa fie unic in baza de date.
table
Este tabela pe care este executat triggerul. View-uri nu pot fi
specificate.
WITH ENCRYPTION
Criptează intrările syscomments care conţin textul a CREATE
TRIGGER.
{ [DELETE] [,] [INSERT] [,] [UPDATE] } | { [INSERT] [,] [UPDATE]}
Sun cuvinte cheie care specifica care instrucţiuni de modificare a
datelor activează triggerul. Orice combinaţie intre acestea in orice
ordine este permisa in definiţia unui trigger.
7
WITH APPEND
Specifică ca un trigger suplimentar a unui tip existent ar trebui
adăugat. Folosirea acestei clauze opţionale este necesara cînd nivelul de
compatibilitate este mai mic sau egal cu 65.
NOT FOR REPLICATION
Indica ca triggerul nu ar trebui executat cînd un proces de replicare
modifica tabela implicata in trigger.
AS
Sunt acţiunile pe care face triggerul.
sql_statement
Este condiţia (conditiile) si acţiunea (actiunile) triggerului.
n
Este indicator de poziţie care indica ca mai multe instrucţiuni
Transact-SQL pot fi incluse intr-un trigger.
IF UPDATE (column)
Testează pentru o acţiune INSERT sau UPDATE la o coloana
specificata si nu este folosita cu operaţii DELETE.
column
Este numele coloanei pentru testare pentru fiecare din acţiunile
INSERT sau UPDATE. Aceasta coloana poate fi de orice tip de date
suportat de SQL Server.
IF (COLUMNS_UPDATED())
Testează, doar intr-un trigger de INSERT sau UPDATE, daca coloana
sau coloanele menţionate au fost inserata sau modificata.
bitwise_operator
Este operatorul pe biţi folosit in comparaţii.
updated_bitmask
Este masca de biţi convertită la întreg a acestor coloane modificate
sau inserate.
comparison_operator
8
Este operatorul de comparare.
column_bitmask
Este masca de biţi convertita la întreg a acestor coloane pentru a
verifica daca ele sunt modificate sau inserate.
Exemple
Folosind baza de date „Complex Sportiv”(vezi anexa)voi crea cîteva triggere
utilizînd argumentele specificate mai sus
9
C. Folosirea COLUMNS_UPDATED
Acest exemplu creaza doua tabele: o tabela employeeData si o tabela
auditEmployeeData. Tabele employeeData, cate tine informatii despre statele de plata ale
angajatilor, poate fi modificata de membrii departamentului de resurse umane. Daca numarul de
securitate social (SSN), salariul anual sau numarul de cont bancar este modificat, o inregistrare
de revizie contabila este generata si inserata in tabela de revizie auditEmployeeData.
Folosind functia COLUMNS_UPDATED(), este posibil a se testa rapid pentru orice
modificari a acelor coloane care contin informatii despre angajati.
USE pubs
10
FOR update AS
-- Check whether columns 2, 3 or 4 has been updated. If any or all of
-- columns 2, 3 or 4 have been changed, create an audit record.
-- The bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14
-- To check if all columns 2, 3, and 4 are updated, use = 14 in place of
-- >0 (below).
IF (COLUMNS_UPDATED() & 14) > 0
-- Use IF (COLUMNS_UPDATED() & 14) = 14 to see if all of columns 2, 3,
-- and 4 are updated.
BEGIN
-- Audit OLD record.
INSERT INTO auditEmployeeData
(audit_log_type,
audit_emp_id,
audit_emp_bankAccountNumber,
audit_emp_salary,
audit_emp_SSN)
SELECT 'OLD',
del.emp_id,
del.emp_bankAccountNumber,
del.emp_salary,
del.emp_SSN
FROM deleted del
-- Audit NEW record.
INSERT INTO auditEmployeeData
(audit_log_type,
audit_emp_id,
audit_emp_bankAccountNumber,
audit_emp_salary,
audit_emp_SSN)
SELECT 'NEW',
ins.emp_id,
ins.emp_bankAccountNumber,
ins.emp_salary,
ins.emp_SSN
FROM inserted ins
END
GO
--Inserting a new employee does not cause the UPDATE trigger to fire.
INSERT INTO employeeData
VALUES ( 101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland',
32)
GO
-- Updating the employee record for employee number 101 to change the
11
-- salary to 51000 causes the UPDATE trigger to fire and an audit trail
-- to be produced.
UPDATE employeeData
SET emp_salary = 51000
WHERE emp_id = 101
GO
SELECT * FROM auditEmployeeData
GO
--Updating the employee record for employee number 101 to change both the
bank account number and social security number (SSN) causes the UPDATE
trigger to fire and an audit trail to be produced.
UPDATE employeeData
SET emp_bankAccountNumber = '133146A0', emp_SSN = 'R-M53550M'
WHERE emp_id = 101
GO
SELECT * FROM auditEmployeeData
GO
12
Instructiunile de modificare a datelor care activeaza triggerele. Optiunile valide
sunt INSERT, UPDATE sau DELETE. Mai multe instructiuni de modificare a
datelor pot activa acelasi trigger. De exemplu, un trigger poate fi activat de oricare
din instructiunile INSERT sau UPDATE.
Instructiunile de programare care executa operatii in baza de date.
13
Vizualizarea dependentelor unui trigger cu Enterprise Manager
Se fac urmatorii pasi:
1. Se extinde un grup de servere si apoi se extinde un server.
2. Se extinde Databases, se extinde baza de date din care apartine triggerul si apoi se
da click pe Tables.
3. In panoul de detalii, se da click dreapta pe tabela caruia apartine triggerul, se indica
All Tasks, si apoi se da click pe Display Dependencies....
4. In Object, se da click pe numele triggerului a carui dependenta se doreste afisata.
14
15
Vizualizarea dependentelor unui trigger cu Enterprise Manager
Se fac urmatorii pasi:
2. Se extinde Databases, se extinde baza de date din care apartine tabela care contine
triggerul si apoi se da click pe Tables.
3. In panoul de detalii, se da click dreapta pe tabela pe care exista triggerul, se indica
All Tasks si apoi se da click pe Manage Triggers....
4. In Name, se da click pe numele triggerului care se sterge.
5. Se da click pe Delete.
6. Se confirma stergerea..
16
3. Triggere multiple
O tabelă poate avea triggere multiple de un anumit tip, dar cu nume diferite; fiecare trigger poate
executa funcţii numeroase. Totusi, fiecare trigger se poate aplica unei singure tabele, deşi un
singur trigger se poate aplica tuturor celor trei actiuni utilizator (UPDATE, INSERT si
DELETE).
17
6. Pentru a verifica sintaxa, se da click pe Check Syntax.
18
Odata criptata, definitia triggerului nu poate fi decriptata si nu poate fi vazuta de oricine, inclusiv
proprietarul triggerului sau administratorul de sistem.
B. Instructiunea SET
Cand o aplicatie ODBC se conecteaza la Microsoft SQL Server, serverul seteaza automat aceste
optiuni pentru sesiune:
SET QUOTED_IDENTIFIER ON
SET TEXTSIZE 2147483647
SET ANSI_DEFAULTS ON
SET CURSOR_CLOSE_ON_COMMIT OFF
SET IMPLICIT_TRANSACTIONS OFF
Aceste setari maresc portabilitatea aplicatiilor ODBC. Deoarece aplicatiile bazate pe DB-Library
in general nu seteaza aceste optiuni, triggerele ar trebui testate cu optiunile SET listate mai sus
puse atat pe on cat si pe off. Aceasta asigura ca triggerele lucreaza corect indiferent de optiunile
unei conexiuni particulare care poate avea setari cand este invocat un trigger. Un trigger care
necesita o setare particulara pentru una din aceste optiuni ar trebui emisa o instructiune SET la
inceputul unui trigger. Aceasta instructiune SET va avea efect doar pentru executia triggerului,
cand triggerul este complet, setarea originala este refacuta.
Clauza IF UPDATE (column_name) in definitia unui trigger poate fi folosita pentru a determina
daca o instructiune INSERT sau UPDATE afecteaza o coloana specifica intr-o tabela. Clauza
evalueaza TRUE ori de cate ori coloanei ii este atribuita o valoare.
Pentru ca o valoare specifica intr-o coloana nu poate fi stearsa folosind instructiunea DELETE,
clauza IF UPDATE nu se aplica instructiunii DELETE.
Alternativ, clauza IF COLUMNS_UPDATED() poate fi folosita pentru a verifica care coloana
intr-o tabela a fost modificata de o instructiune INSERT sau UPDATE. Aceasta clauza foloseste
o masca de biti intreaga pentru a specifica care coloane sa se testeze.
Exemple
Exemplul urmator creaza un trigger INSERT my_trig pe tabela my_table si testeaza daca
coloana b a fost afectata de orice instructiuni INSERT.
CREATE TABLE my_table
(a int NULL, b int NULL)
GO
CREATE TRIGGER my_trig
ON my_table
FOR INSERT
19
AS
IF UPDATE(b)
PRINT 'Column b Modified'
GO
Se pot obtine rezultate similare folosind clauza
COLUMNS_UPDATED():
CREATE TRIGGER my_trig2
ON my_table
FOR INSERT
AS
IF ( COLUMNS_UPDATED() & 2 = 2 )
PRINT 'Column b Modified'
GO
D. Intîrzierea rezolutiei numelui
SQL Server permite triggerelor sa se refere la tabele care nu exista in momentul crearii
triggerului. Aceasta se numeste intarzierea rezolutiei numelui.
E. Returnarea rezultatelor
20
UPDATE employee SET hire_date = '7/1/94' WHERE emp_id =
'VPA30890F'
INSERT employee VALUES ('XYZ12345M', 'New', 'M', 'Employee', 1,
1, '9952', '6/1/95') -- Causes trigger to fire and ROLLBACK
TRANSACTION
6. Consideratii multilinie
O consideratie importanta de retinut cand se scrie cod pentru un trigger este ca instructiunea care
cauzeaza ca triggerul sa se declanseze poate fi o singura instructiune care afecteaza mai degraba
multiple linii de date decat o singura linie. Aceasta este obisnuit pentru triggere UPDATE si
DELETE pentru ca aceste instructiuni deseori afecteaza multiple linii. Este mai putin obisnuit
pentru triggerele INSERT pentru ca instructiunea INSERT fundamentala introduce o singura
linie. Totusi, de cand un trigger INSERT poate fi declansat de catre o instructiune INSERT
INTO (table_name) SELECT, sute de linii pot fi afectate de un trigger INSERT.
21
Consideratiile multilinie sunt in particular importante cand functia unui trigger este de a
recalcula automat valori de tip rezumat dintr-o tabela si sa stocheze rezultatul in alta tabela.
Exemple
Triggerele din exemplele urmatoare sunt proiectate pentru a stoca un total neintrerupt de coloane
in alta tabela. Prima versiune a triggerului lucreaza bine pentru o singura linie inserata, cand o
linie de date este incarcata in tabela sales. Triggerul este declansat de o instructiune INSERT si
noua linie este incarcata in tabela inserted pe durata executarii triggerului. Instructiunea
UPDATE citeste valoarea coloanei qty pentru linie si o adauga la valoarea existenta in coloana
ytd_sales din tabela titles. Clauza WHERE asigura ca linia modificata in tabela sales se
potriveste cu title_id a liniei din tabela inserted.
-- Trigger valid for single row INSERTS.
CREATE TRIGGER intrig
ON sales
FOR INSERT AS
UPDATE titles
SET ytd_sales = ytd_sales + qty
FROM inserted
WHERE titles.title_id = inserted.title_id
In cazul unui INSERT multilinie, acest trigger poate sa nu opereze corect; expresia din dreapta
expresiei de atribuire intr-o instructiune UPDATE (ytd_sales + qty) poate fi doar o singura
valoare, nu o lista de valori. Deci efectul triggerului este sa obtina o valoare din orice linie
singulara in tabela inserted si sa o adauge la valoarea existenta ytd_sales in tabela titles pentru
o valoare title_id data. Aceasta poate sa nu aiba efectul dorit daca o singura valoare title_id
apare mai mult decat o data tabela inserted.
Pentru a modifica corect tabela titles, triggerul trebuie sa ia in calcul posibilitatea existentei
liniilor multiple in table inserted. Aceasta poate fi facuta cu functia SUM care calculeaza totalul
qty pentru un grup de linii in tabela inserted pentru fiecare title_id. Functia SUM este plasata
intr-un subquery corelat (instructiunea SELECT in paranteze), care returneaza o singura valoare
pentru fiecare title_id in tabela inserted care se potriveste sau este corelata cu un title_id in
tabela titles.
-- Trigger valid for multirow and single row inserts.
CREATE TRIGGER intrig
ON sales
FOR INSERT AS
UPDATE titles
SET ytd_sales = ytd_sales +
(SELECT SUM(qty) -- Correlated subquery.
FROM inserted
WHERE titles.title_id = inserted.title_id)
WHERE titles.title_id IN
(SELECT title_id FROM inserted)
22
Acest trigger lucreaza de asemenea corect la inserarea unei singure linii; suma valorii coloanei
qty este suma unei singure linii. Totusi, cu acest trigger subquery-ul corelat si operatorul IN
folosit in clauza WHERE necesita prelucrare suplimentara din parte a Microsoft SQL Server,
care este inutila pentru o singura linie inserata. De aceea, se poate modifica triggerul pentru a
folosi metode optimale pentru numarul de linii. De exemplu, functia @@ROWCOUNT poate
folosita in logica triggerului pentru a distinge intre o singura linie sau multilinie inserata.
-- Trigger valid for multirow and single row inserts
-- and optimal for single row inserts.
CREATE TRIGGER intrig
ON sales
FOR INSERT AS
IF @@ROWCOUNT = 1
BEGIN
UPDATE titles
SET ytd_sales = ytd_sales + qty
FROM inserted
WHERE titles.title_id = inserted.title_id
END
ELSE
BEGIN
UPDATE titles
SET ytd_sales = ytd_sales +
(SELECT SUM(qty)
FROM inserted
WHERE titles.title_id = inserted.title_id)
WHERE titles.title_id IN
(SELECT title_id FROM inserted)
END
‚’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’
Exemple
Exemplul urmator presupune existenta unei tabele numita newsale in baza de date pubs. Aici
este o instructiune CREATE pentru newsale:
CREATE TABLE newsale
(stor_id char(4),
ord_num varchar(20),
date datetime,
qty smallint,
payterms varchar(12),
title_id tid)
23
Daca se doreste sa se examineze fiecare dintre inregistrari se poate incerca sa se insereze,
triggerul conditionalinsert analizeaza inserarea linie dupa linie si apoi sterge liniile care nu au
un title_id in titles.
CREATE TRIGGER conditionalinsert
ON sales
FOR INSERT AS
IF
(SELECT COUNT(*) FROM titles, inserted
WHERE titles.title_id = inserted.title_id) <> @@ROWCOUNT
BEGIN
DELETE sales FROM sales, inserted
WHERE sales.title_id = inserted.title_id AND
inserted.title_id NOT IN
(SELECT title_id
FROM titles)
PRINT 'Only sales records with matching title_ids added.'
END
Cand titluri inacceptabile au fost inserate, tranzactia nu este facuta roll back; in schimb, triggerul
sterge liniile nedorite. Aceasta abilitate de a sterge linii care au fost inserate depinde de ordinea
in care apare procesarea cand triggerele sunt declansate. Mai intai, liniile sunt inserate in tabela
si in tabela inserted si apoi triggerul este declansat.
Pentru a testa triggerul, se introduc patru linii in tabela newsale. Doua din linii au title_ids care
nu se potriveste cu nici una din tabela titles.
newsale
stor_id Ord_num date qty payterms title_id
------- -------- ----------- --- -------- --------
7066 QA7442.3 Jul 25 1995 8:35AM 75 Net 30 PS1372
7066 QA7442.3 Jul 24 1995 8:35AM 75 Net 60 BU7832
7067 D4482 Jul 27 1995 12:00AM 10 Net 30 PSxxxx
7131 N914008 Jul 27 1995 12:00AM 20 Net 30 PSyyyy
Apoi se introduc date din newsale in sales. Instructiunea arata astfel:
INSERT sales
SELECT * FROM newsale
Title _indb-urile PSxxxx si Psyyyy nu se potriveste nici unul in tabela titles si triggerul
conditionalinsert sterge aceste doua linii din tabelele sales si inserted.
24
8. Valori NULL implicite si explicite
Introducand o valoare explicita nula intr-o coloana sau folosind cuvantul cheie DEFAULT
pentru a atribui o valoare unei coloane activeaza triggerul asa cum se astepta. Similar, cand nici
o valoare nu este specificata in instructiunea INSERT pentru o coloana, triggerul este activat
cînd:
O valoare nula implicita este inserata intr-o coloana pentru ca nu exista nici o
definitie DEFAULT.
O valoare implicita este inserata intr-o coloana pentru ca nu exista o definitie
DEFAULT.
Exemple
CREATE TABLE junk
(a int NULL, b int NOT NULL DEFAULT 99)
GO
CREATE TRIGGER junktrig
ON junk
FOR INSERT, UPDATE
AS
IF UPDATE(a) AND UPDATE(b)
PRINT 'FIRING'
GO
INSERT junk (a, b) /*IF UPDATE is true for both columns, */
VALUES (1, 2) /*the trigger is activated. */
UPDATE junk /*IF UPDATE is true for both columns, */
SET a = 1, b = 2 /*the trigger is activated. */
INSERT junk /*Explicit NULL. */
VALUES (NULL, 2) /*IF UPDATE is true for both columns, */
/*the trigger is activated. */
UPDATE junk /*IF UPDATE is true for both columns, */
SET a = NULL, b = 2 /*the trigger is activated. */
INSERT junk (b) /*No default on column a. */
VALUES (2) /*IF UPDATE is true for both columns, */
/*the trigger is activated. */
UPDATE junk /*IF UPDATE is not true for both columns, */
SET b = 2 /*the trigger is not activated. */
INSERT junk (a) /*Default on column b. */
VALUES (2) /*IF UPDATE is true for both columns, */
/*the trigger is activated. */
UPDATE junk /*IF UPDATE is not true for both columns, */
SET a = 2 /*the trigger is not activated. */
INSERT junk (a, b) /*DEFAULT explicitly inserted. */
VALUES (2, DEFAULT) /*IF UPDATE is true for both columns, */
/*the trigger is activated. */
UPDATE junk /*IF UPDATE is true for both columns, */
SET a = 2, b = DEFAULT /*the trigger is activated. */
25
9. Triggere încuibărite
Triggerele sunt incuibarite cand un trigger executa o actiune care initiaza alt trigger, care poate
initia alt trigger si tot asa. Triggerele pot fi incuibarite pana la 32 nivele si se poate controla daca
triggerele pot fi incuibarite prin optiunea de configurare a serverului nested triggers.
Daca triggerele incuibarite sunt permise si un trigger intr-un lant seteaza off o bucla infinita,
nivelul de incuibarire este depasit si triggerul se termina.
Se pot folosi triggerele incuibarite pentru a executa functii de administrare utile cum ar fi
stocarea unei copii de linii salvate, afectate de un trigger anterior. De exemplu, se poate crea un
trigger pe titleauthor care salveaza o copie (backup) pe liniile titleauthor care triggerul
delcascadetrig le-a sters. Cu triggerul delcascadetrig in vigoare, stergand title_id PS2091 din
tabela titles sterge linia sau liniile corespondente din titleauthor. Pentru a salva datele, se creaza
un trigger DELETE pe titleauthor care salveaza datele sterse, intr-o alta tabela creata separat,
del_save.
CREATE TRIGGER savedel
ON titleauthor
FOR DELETE
AS
INSERT del_save
SELECT * FROM deleted
Nu este o buna idee sa se foloseasca triggere incuibarite intr-o secventa dependenta de ordine. Se
folosesc triggere separate pentru a cascada modificarile datelor.
Triggere recursive
Un trigger nu declanseaza pe el insusi recursiv, pana cand optiunea bazei de date Recursive
Triggers este setata. Exista doua tipuri diferite de recursivitati:
Recursivitatea directa, care apare cand un trigger este declansat si executa o actiune
care cauzeaza acelasi trigger sa fie declansat din nou. De exemplu, o aplicatie
modifica tabela T3, care cauzeaza declansarea triggerului Trig3. Acesta modifica
tabela T3 din nou, care cauzeaza declansarea triggerului Trig3 din nou.
Recursivitatea indirecta, care apare cand un trigger este declansat si executa o
actiune care cauzeaza declansarea unui trigger pe alta tabela. Acest al doilea trigger
cauzeaza aparitia unei modificari pe tabela originala, care cauzeaza ca triggerul
original sa fie declansat din nou. De exemplu, o aplicatie modifica tabela T1, care
cauzeaza declansarea triggerului Trig1. Acesta modifica tabela T2, care cauzeaza
declansarea triggerului Trig2 care la randul lui modifica tabela T1 care cauzeaza
declansarea triggerului Trig1 din nou.
26
Exemple
O utilizare pentru triggerii recursivi este pe o tabela cu o relatie spre ea insesi (cunoscuta ca si
incheiere tranzitiva). De exemplu, tabela emp_mgr defineste:
Un angajat (emp) intr-o companie.
Conducatorul fiecarui angajat (mgr).
Numarul total de angajati in arborele organizatoric raportat la fiecare angajat
(NoOfReports).
Un trigger de modificare recursiv poate fi folosit pentru a pastra coloana NoOfReports la zi pe
parcurs ce sunt inserate noi inregistrari de angajati. Triggerul de inserare modifica coloana
NoOfReports a inregistrarii de administrare, care modifica recursiv coloana NoOfReports a
altor inregistrari pana la ierarhia de management.
USE pubs
GO
-- Turn recursive triggers ON in the database.
EXECUTE sp_dboption 'pubs', 'recursive triggers', TRUE
GO
CREATE TABLE emp_mgr (
emp char(30) PRIMARY KEY,
mgr char(30) NULL FOREIGN KEY REFERENCES emp_mgr(emp),
NoOfReports int DEFAULT 0
)
GO
CREATE TRIGGER emp_mgrins ON emp_mgr
FOR INSERT
AS
DECLARE @e char(30), @m char(30)
DECLARE c1 CURSOR FOR
SELECT emp_mgr.emp
FROM emp_mgr, inserted
WHERE emp_mgr.emp = inserted.mgr
OPEN c1
FETCH NEXT FROM c1 INTO @e
WHILE @@fetch_status = 0
BEGIN
UPDATE emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1 -- add 1
for newly
WHERE emp_mgr.emp = @e -- added
employee
FETCH NEXT FROM c1 INTO @e
END
CLOSE c1
DEALLOCATE c1
GO
-- This recursive UPDATE trigger works assuming:
-- 1. Only singleton updates on emp_mgr.
-- 2. No inserts in the middle of the org tree.
CREATE TRIGGER emp_mgrupd ON emp_mgr FOR UPDATE
AS
IF UPDATE (mgr)
BEGIN
UPDATE emp_mgr
27
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1--increment
mgr's
FROM inserted -- (no. of reports) by
WHERE emp_mgr.emp = inserted.mgr -- 1 for the new report.
UPDATE emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports - 1 --
increment mgr's
FROM deleted -- (no. of reports) by 1
WHERE emp_mgr.emp = deleted.mgr -- for the new report
END
GO
-- Insert some test data rows.
INSERT emp_mgr(emp, mgr) VALUES ('Harry', NULL)
INSERT emp_mgr(emp, mgr) VALUES ('Alice', 'Harry')
INSERT emp_mgr(emp, mgr) VALUES ('Paul', 'Alice')
INSERT emp_mgr(emp, mgr) VALUES ('Joe', 'Alice')
INSERT emp_mgr(emp, mgr) VALUES ('Dave', 'Joe')
GO
SELECT * FROM emp_mgr
GO
-- Change Dave's manager from Joe to Harry
UPDATE emp_mgr SET mgr = 'Harry'
WHERE emp = 'Dave'
GO
SELECT * FROM emp_mgr
GO
Aici sunt rezultatele inainte de modificare:
emp mgr
NoOfReports
------------------------------ -----------------------------
-----------
Alice Harry 2
Dave Joe 0
Harry NULL 1
Joe Alice 1
Paul Alice 0
Aici sunt rezultatele dupa modificare:
emp mgr
NoOfReports
------------------------------ -----------------------------
-----------
Alice Harry 2
Dave Harry 0
Harry NULL 2
Joe Alice 0
Paul Alice 0
Setarea optiunii triggerelor incuibarite cu Enterprise Manager
Se fac urmatorii pasi:
1. Se extinde un grup de servere.
2. Se da click dreapta pe un server, apoi se da click pe Properties.
3. Se da click pe tab-ul Server Settings.
28
4. In casuta Server behavior, se selecteaza sau deselecteaza Allow triggers to be
fired which fire other triggers (nested triggers).
29
30
Capitolul II Crearea şi executarea triggerilor
31
constraint CK_tel_antrenor check(tel_antrenor like '[1-9][0-9]-[0-9][0-9]-[0-9][0-9]')
)
Insert into antrenor values(1,'Teberneac','Dinu', '01.01.1968','49-34-22')
Insert into antrenor values(2,'Berzoi', 'Nicolaie','03.20.1970','48-96-21')
Insert into antrenor values(3,'Lesnic', 'Nicolaie','09.05.1970','40-05-36')
Insert into antrenor values(4,'Ceobotari','Ana','08.14.1968','48-45-65')
33
id_antrenor int Not Null,
id_disc int Not Null,
constraint FK_id_antrenor Foreign Key(id_antrenor)references antrenor(id_antrenor) on
update cascade,
constraint FK_id_disc Foreign Key(id_disc)references disciplina(id_disc) on update cascade
)
Insert into echipa values(1,2,1)
Insert into echipa values(2,1,2)
Insert into echipa values(3,3,3)
34
1.2 Crearea şi executarea declanşatoarelor asupra bazei date
/*De creat un trigger ce nu va permite modificarea cimpului salariu antrenorilor*/
/*De creat un trigger de adaugare la tabela sportivi ,ce ar permite verificarea numarului de
sportivi pentru a indica daca este necesar de a inscrie un sportiv nou.Daca inscrierea este >10
nu-i permitem sa-l inscrie*/
begin transaction
update antrenor
set salariu=salariu*1.2
where(nume like 'T%')
commit transaction
/*De creat un trigger ce nu permite adaugarea sau modificarea unui nou antrenor
cu datele personale deja existente in BD*/
Concluzie
În urma efectuării acestei lucrări şi implementării informaţiei teoretizate
despre SQL Server am acumulat cunoştinţe multilaterale în domeniul
Sistemelor Infomatice şi a Tehnologiilor de Programare în special ceia ce ţine
de operaţionalizarea datelor stocate intr-o B.D. Dar cea mai mare atenţie a fost
acordată aşa numitelor Declanşatoare sau Triggere. Definind noţiunile de bază
şi analizînd crearea , executarea şi aplicarea declanşatoarelor în SQL m-am
convins practic de rolul lor şi a avntajelor de utilizare. Am conştientiezat că
triggerii sunt nişte proceduri memorate strîns legate de careva evenimente în
B.D care duc la modificarea de stare a bazelor de date menţinînd în mod
39
automat integritatea datelor. De asemenea m-am familiarizat cu toate
instrucţiunile şi comenzile de creare şi executare a triggerilor cum ar fi de:
INSERT, UPDATE şi DELETE. Analizînd baza de date „Complex Sportiv” şi
efectuînd asupra ei un număr de declanşatoare, am realizat cum acestea
acţionează asupra manipularii datelor. La rîndul său m- am convins cum sunt
acestea apelate ca rezultat al unor evenimente ca de exemplu: transmiterea
automată a mesajelor unor altor aplicaţii care lucrează cu tabela pe care se
crează triggerul. Pe parcursul executării lor am observat legătura lor cu
Sistemul ce le aplică.
Bibliografie:
40
41