Sunteți pe pagina 1din 41

Ministerul Educaţiei, Ştiinţei şi Sportului

Universitatea de Stat din Moldova


Facultatea de Matematică şi Informatică
Catedra de Informatică Aplicată

Tema:

DECLANŞATOARE ÎN SQL SERVER

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

Capitolul II. Crearea şi executarea triggerelor

1. Crearea B. D „Complex Sportiv”.......................................................................29


2. Crearea şi executarea declanşatoarelor asupra bazei date..................................33

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

1. Notiuni generale despre Triggere


Un trigger(declanşator) este un tip special de procedura stocata care este
automat invocata ori de cate ori datele in tabela sunt modificate.
Triggerele(Declanşatoarele) sunt invocate ca răspuns la instrucţiunile INSERT,
UPDATE sau DELETE. Un trigger poate interoga alte tabele si poate include
instrucţiuni complexe Transact-SQL. Triggerul(Declanşatorul) si instrucţiunea care
îl declanşează sunt tratate ca o tranzacţie singulara care poate fi rollback din
interiorul triggerului. Daca o eroare severă este detectată întreaga tranzacţie
execută automat rollback.

1.1. Importanţa şi avantajele utilizării Triggerelor


Triggerele sunt utile in urmatoarele moduri:

 Triggerele pot modifica tabelele legate in baza de date.


 Declanşatoarele sunt automate: ele se activează imediat după unele
modificări ale datelor în tabelă, astfel ca intrare/înregistrare manuală
sau o acţiune aplicată.
De exemplu, utilizînd baza de date „Complex Sportiv” din anexă un
trigger de delete pe coloana id_antrenor a tabelei autor cauzează o
ştergerea corespondenta a liniilor din alte tabele, folosind coloana
id_antrenor ca o cheie unica pentru a localiza liniile ca de exemplu in
tabela echipa.
 Triggerele pot refuza sau rollback modificările care violează
integritatea referenţială, prin aceasta anulînd modificările de date
încercate.
Ca atare un trigger îşi poate face efectul cînd se modifica o cheie
străina si noua valoare nu se potriveşte cu cheia ei primara. De

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.

1.2. Triggerele si performanţa


Performanţa triggerelor ‘overhead’ este uzual scăzuta. Timpul implicat in rularea
unui trigger este consumat majoritatea in indicarea altor tabele, care pot fi fiecare
in memorie sau pe un dispozitiv al bazei de date. Tabelele deleted si inserted sunt
întotdeauna în memorie.

2. Crearea unui Declanşator. Instrucţiunea „Create Trigger”


Această instrucţiune crează un trigger(declanşator) care este un tip special de
procedură stocată care se executa automat cînd un utilizator face instrucţiuni de
modificare a datelor specificate pe o tabela specificată. Microsoft SQL Server
permite crearea mai multor triggere pentru orice instrucţiune INSERT, UPDATE
sau DELETE data.

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

A. Folosirea unui trigger cu un mesaj


Acest trigger afişează un mesaj clientului cînd oricine încearcă să adauge
sau să modifice date in tabela competitii.
USE compsport
IF EXISTS (SELECT name FROM sysobjects
        WHERE name = 'reminder' AND type = 'TR')
    DROP TRIGGER reminder
GO
CREATE TRIGGER reminder
ON competitii
FOR INSERT, UPDATE
AS RAISERROR (‘nu puteţi face nici o modificare’, 16, 10)
GO
 
B. Folosirea Acţiunii UPDATE la crearea unui trigger
Acest exemplu creaza un trigger ce nu fa permite modificarea cîmpului
Nume de pe tabela antrenor
USE compsport
Create or trigger modif on Antrenor
for update
as
if update(salariu) begin
raiserror('nu puteti modifica valorile cimpului salariu',16,1)
rollback transaction
end

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

IF EXISTS(SELECT TABLE_NAME FROM


INFORMATION_SCHEMA.TABLES
        WHERE TABLE_NAME = 'employeeData')
    DROP TABLE employeeData
IF EXISTS(SELECT TABLE_NAME FROM
INFORMATION_SCHEMA.TABLES
        WHERE TABLE_NAME = 'auditEmployeeData')
    DROP TABLE auditEmployeeData
GO
CREATE TABLE employeeData (
        emp_id                int NOT NULL,
        emp_bankAccountNumber char (10) NOT NULL,
        emp_salary            int NOT NULL,
        emp_SSN               char (11) NOT NULL,
        emp_lname             nchar (32) NOT NULL,
        emp_fname             nchar (32) NOT NULL,
        emp_manager           int NOT NULL
        )
GO
CREATE TABLE auditEmployeeData (
        audit_log_id                uniqueidentifier DEFAULT NEWID(),
        audit_log_type              char (3) NOT NULL,
        audit_emp_id                int NOT NULL,
        audit_emp_bankAccountNumber char (10) NULL,
        audit_emp_salary            int NULL,
        audit_emp_SSN               char (11) NULL,
        audit_user                  sysname DEFAULT SUSER_SNAME(),
        audit_changed               datetime DEFAULT GETDATE()
        )
GO
  
CREATE TRIGGER updEmployeeData
ON employeeData

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

2.1. Reguli de crearea a unui trigger


Inainte de a crea un trigger se ia in consideraţie:

   Instructiunea CREATE TRIGGER trebuie sa fie prima instructiune in batch.


 Permisiunea de a crea triggere o are implicit proprietarul tabelei, care nu poate sa o
transfere altor utilizatori.
 Triggerele sunt obiecte ale bazei de date si numele lor trebuie sa urmareasca
regulile pentru identificatori.
 Se poate crea un trigger doar in baza de date curenta, desi un trigger poate indica
obiecte din afara bazei de date curente.
   Un trigger nu poate fi creat pe un view, tabela temporara sau sistem, desi triggerele
pot indica view-uri sau tabele temporare. Tabelele sistem nu ar trebui indicate, se
foloseste in schimb Information Schema Views.
   Desi o instructiune TRUNCATE TABLE este ca si o instructiune DELETE fara o
clauza WHERE (sterge toate liniile), nu face ca triggerele DELETE sa se
declanseze pentru ca instructiunea TRUNCATE TABLE nu este logată.
 Instructiunea WRITETEXT nu face ca triggerele INSERT sau UPDATE sa se
declanşeze.
Cînd se crează un trigger se specifica:
 Numele.
 Tabela pe care triggerul este definit.

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.

   2.2. Redenumirea triggerelor Redactarea


Daca e nevoie sa se modifice continutul unui unui trigger, se poate ori sa se şteargă si sa
se recreeze triggerul sau sa se redefinească triggerul existent intr-un singur pas. Dacă se
modifică numele unui obiect indicat de trigger, trebuie modificat triggerul astfel ca textul sau sa
reflecte noul nume. Deci, inainte de a redenumi un obiect, se afiseaza mai intai dependentele
obiectului pentru a determina daca ceva triggere sunt afectate de modificarea propusa.
Se poate de asemenea redenumi un trigger. Noul nume trebuie sa urmareasca regulile pentru
identificatori. Se pot redenumi numai triggerele care ii apartin, dar proprietarul bazei de date
poate modifica numele oricarui trigger utilizator. Triggerul pentru a fi redenumit trebuie sa fie in
baza de date curenta. Un trigger poate de asemenea modificat pentru a cripta definitia lui.

Modificarea unui trigger cu Enterprise Manger


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 tabela care contine
triggerul si se da click pe Tables.
3. In panoul de detalii, se da click dreapta pe tabela pe care s-a construit triggerul, se
indica All Tasks, si apoi se da click pe Manage Triggers....
4. In Name, se selecteaza numele triggerului.
5. Se modifica continutul triggerului in campul Text cat este necesar. Se apasa
CTRL+TAB pentru a indenta textul unui trigger SQL Server Enterprise Manager.
6. Pentru a verifica sintaxa triggerului, se da click pe Check Syntax.

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
  

               2.3. Vizualizarea unui trigger


Microsoft SQL Server permite determinarea tipului de triggere pe o tabela, numele triggerului,
proprietarul lui si data la care a fost creat.
De asemenea se mai poate:
 Obtine informatii despre definitia unui trigger daca nu a fost criptata cand a fost
creat sau modificat. S-ar putea avea nevoie sa se vada definitia triggerului,
instructiunile Transact-SQL sau a intelege cum afecteaza tabela pe care este definit.
 Lista obiectele folosite de un trigger specificat. Aceasta informatie poate fi folosita
pentru a identifica obiectele care afecteaza triggerul daca ele sunt modificate sau
sterse din baza de date.
Vizualizarea 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 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..

15
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 de care 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 sa se
afiseze.

                    2.4. Ştergerea unui trigger


Este indicat ca sa se ştearga un trigger cand nu mai este nevoie de el. Cand un trigger este şters,
tabela si datele pe care este bazat nu sunt afectate. Stergand o tabela, automat se sterge orice
trigger pe tabela. Permisiunile de a sterge un trigger le are implicit proprietarul tabelei pe care
este definit triggerul.

Stergerea 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 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).

Crearea 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 in care este tabela de care apartine
triggerul si se da click pe Tables.
3. In panoul de detalii, se da click dreapta pe tabela pe care triggerul va fi creat, se
pointeaza All Tasks si apoi se da click pe Manage Triggers....
4. In Name se da click pe <new>.
5. In casuta Text, se introduce textul triggerului. Se foloseste CTRL-TAB pentru a
indenta textul triggerului.

17
6. Pentru a verifica sintaxa, se da click pe Check Syntax.

    4. Programarea triggerelor


Aproape orice cod Transact-SQL care poate fi scris ca si un batch poate fi folosit pentru a crea
un trigger, exceptand urmatoarele:

ALTER DATABASE ALTER PROCEDURE ALTER TABLE


ALTER TRIGGER ALTER VIEW CREATE DATABASE
CREATE DEFAULT CREATE INDEX CREATE PROCEDURE
CREATE RULE CREATE SCHEMA CREATE TABLE
CREATE TRIGGER CREATE VIEW DENY
DISK INIT DISK RESIZE DROP DATABASE
DROP DEFAULT DROP INDEX DROP PROCEDURE
DROP RULE DROP TABLE DROP TRIGGER
DROP VIEW GRANT LOAD DATABASE
LOAD LOG RESTORE DATABASE RESTORE LOG
REVOKE RECONFIGURE  
TRUNCATE TABLE UPDATE STATISTICS  
 

A.Criptarea definitiilor triggerelor

Daca se creaza un trigger si se doreste ca definitia acestuia sa nu poata fi vizualizata de alti


utilizatori, se poate folosi clauza WITH ENCRYPTION. Definitia triggerului este atunci stocata
intr-o forma ilizibila.

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.

C. Testari pentru modificarile coloanelor specifice

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

Este recomandat ca un trigger sa nu returneze nici un rezultat pentru ca manipularea speciala


pentru aceste rezultate returnate trebuie scrise in fiecare aplicatie in care modificarile tabelei
triggerului sunt permise. Pentru a preveni ca nici un rezultat sa nu fie returnat de un trigger, nu se
include nici o instructiune SELECT sau atribuiri de variabila in definitia unui trigger. Daca
atribuirea de variabila trebuie sa apara intr-un trigger, se foloseste o instructiune SET
NOCOUNT la inceputul triggerului pentru a elimina returnarea oricarui set de rezultate.

5.Triggere ROLLBACK TRANSACTION


Cand triggerele care includ instructiuni ROLLBACK TRANSACTION sunt executate dintr-un
batch, ele anuleaza intreg batch-ul. In exemplul urmator, daca instructiunea INSERT declanseaza
un trigger care include o instructiune ROLLBACK TRANSACTION, instructiunea DELETE nu
este executata pentru ca batch-ul este anulat:
/* Start of Batch */
INSERT employee VALUES ('XYZ12345M', 'New', 'M', 'Employee', 1,
1, '9952', '6/1/95') -- Causes trigger to fire and ROLLBACK
TRANSACTION
DELETE employee WHERE emp_id = 'PMA42628M'
GO
Daca triggerele care includ instructiuni ROLLBACK TRANSACTION sunt declansate dintr-o
tranzactie definita de utilizator, ROLLBACK TRANSACTION face rollback intrega tranzactie.
In acest exemplu, daca instructiunea INSERT declanseaza un trigger care include o instructiune
ROLLBACK TRANSACTION, instructiunea UPDATE este de asemenea facuta rollback:
/* Start of Transaction */
BEGIN TRANSACTION

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
  

5.1. Folosirea tabelelor speciale inserted si deleted


Doua tabele speciale sunt folosite in instructiunile triggerului: tabela deleted si tabela inserted.
Se pot folosi aceste tabele temporare pentru a testa efectele modificarilor datelor sigure si pentru
a seta conditii pentru actiunile triggerelor. Nu se pot modifica tabelele test ale triggerului direct,
dar se pot folosi tabelele in instructiunea SELECT pentru a determina care trigger a fost
declansat de o instructiune INSERT, UPDATE sau DELETE.
Tabela deleted stocheaza copii ale liniilor afectate in timpul instructiunilor DELETE si
UPDATE. In timpul executarii acestor instructiuni, liniile sunt sterse din tabela triggerului si
transferate tabelei deleted. Aceasta si tabela triggerului de obicei nu au linii in comun.
Tabela inserted stocheaza copii ale liniilor afectate in timpul instructiunilor INSERT si
UPDATE. In timpul unei tranzactii INSERT sau UPDATE, noi linii sunt adaugate simultan atat
tabelei inserted cat si tabelei triggerului. Liniile din tabela inserted sunt copii ale noilor linii din
tabela triggerului.
O tranzactie UPDATE este ca o stergere urmata de o inserare, liniile vechi sunt copiate in tabela
deleted mai intai, iar apoi noile linii sunt copiate in tabela triggerului si in tabela inserted. Cand
se seteaza conditiile triggerului, se folosesc tabelele inserted si deleted corespunzator pentru
actiunile care declanseaza triggerul. Desi indicand deleted in tipul testarii unui INSERT, sau
inserted in timpul testarii unui DELETE nu cauzeaza nici o eroare, aceste tabele test ale
triggerului nu contin nici o linie in aceste cazuri.
Microsoft SQL Server nu permite coloanelor text, ntext sau image sa fie indicate in tabelele
inserted si deleted daca nivelul de compatibilitate este 70.

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

‚’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’

7.Trigger de insert conditionat


Un trigger respinge sau accepta fiecare tranzactie de modificare de date ca un intreg. Totusi, nu
trebuie facute roll back toate modificarile de date pentru ca unele din ele sunt inacceptabile.
Folosind un subquery corelat intr-un trigger se poate forta un trigger sa examineze liniile
modificate una cate una.

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

Setarea triggerelor recursive din optiunea bazei de date 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 da click dreapta pe baza de date dorita si apoi se da click


pe Properties.
3. Se da click pe tab-ul Options si se selecteaza sau deselecteaza setarea (setarile) de
configurare pentru a le modifica.

4. Se da click pe tab-ul Options si se selecteaza sau deselecteaza setarea


(setarile) de configurare pentru a le modifica.

29
30
Capitolul II Crearea şi executarea triggerilor

1. Crearea B. D „Complex Sportiv”


use valea
set dateformat mdy
create Table Sectoare(
id_sect tinyint Not Null Primary Key,
den_sect varchar(20)
)
Insert into sectoare values(1,'Riscanovca')
Insert into sectoare values(2,'Telecentru')
Insert into sectoare values(3,'Buiucani')
Insert into sectoare values(4,'Botanica')
Insert into sectoare values(5,'Ciocana')

create Table Disciplina(


id_disc int Not Null primary Key,
den_disc varchar(20),
)
Insert into disciplina values(1,'Baschet')
Insert into disciplina values(2,'Tenes_de_masa')
Insert into disciplina values(3,'Volei')
Insert into disciplina values(4,'Fotbal')
Insert into disciplina values(5,'Hambal')

create Table Antrenor(


id_antrenor int Not Null Primary key,
Nume varchar(20),
Prenume varchar(20),
DN smalldatetime Not Null,
tel_antrenor char(8) Not Null,
constraint CK_DN_a check(DN<=GetDate()-35*365.25 and DN>=GetDate()-60*365.25),

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

create Table Sala(


id_sala tinyint Not Null Primary Key,
etajul tinyint Not Null,
)
Insert into sala values(1,'3')
Insert into sala values(2,'4')
Insert into sala values(3,'2')
Insert into sala values(4,'1')

create Table Strada(


id_strada tinyint Not Null Primary Key,
den_strada varchar(20),
cod_postal char(7),
id_sect tinyint Not Null,
constraint CK_cod_postal check(cod_postal like 'MD-[1-9][0-9][0-9][0-9]'),
constraint FK_sect Foreign Key(id_sect)references sectoare (id_sect) on update cascade
)
Insert into strada values(1,'Alexei Mateevici','MD-2015','2')
Insert into strada values(2,'Florilor','MD-2010','1')
Insert into strada values(3,'Igor Vieru','MD-2020','3')
Insert into strada values(4,'Dacia','MD-2025','4')
Insert into strada values(5,'Maria Ceobotari','MD-2017','5')

create Table Complex(


id_complex int Not Null Primary Key,
den_complex varchar(20),
32
tel_complex char(8) Not Null,
id_strada tinyint Not Null,
bloc varchar(10) Not Null,
constraint CK_tel_complex check(tel_complex like '[1-9][0-9]-[0-9][0-9]-[0-9][0-9]'),
constraint FK_id_strada Foreign Key(id_strada)references strada(id_strada) on update
cascade
)
Insert into complex values(1,'Speranta','54-65-25',3,'2/2')
Insert into complex values(2,'Tineretea','45-20-09',2,'2')
Insert into complex values(3,'Orange Club','73-11-06',4,'2/3')
Insert into complex values(4,'Sanatatea','55-30-12',1,'4')

create Table Competitii(


id_compet int Not Null Primary Key,
id_complex int Not Null,
data_ora smalldatetime,
id_sala tinyint Not Null,
id_disc int Not Null,
constraint FK_id_complex Foreign Key (id_complex)references complex(id_complex) on
update cascade,
constraint CK_data check(data_ora>=GetDate()-25*365.25),
constraint FK_id_sala Foreign Key (id_sala)references sala(id_sala) on update cascade,
constraint FK_id_disc_C Foreign Key(id_disc)references disciplina(id_disc) on update
cascade
)

Insert into competitii values(1,1,'2.10.2006 14:20:00',2,1)


Insert into competitii values(2,3,'3.10.2006 15:45:00',1,5)
Insert into competitii values(3,2,'4.10.2006 10:30:00',3,2)
Insert into competitii values(4,4,'5.10.2006 12:40:00',4,3)

create Table Echipa(


id_echipa int Not Null Primary Key,

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)

create Table Sportivi(


id_sportivi int Not Null Primary Key,
Nume varchar(20),
Prenume varchar(20),
DN smalldatetime Not Null,
id_strada tinyint Not Null,
tel_sportivi char(8) Not Null,
id_echipa int Not Null,
constraint CK_DN check(DN<=GetDate()-18*365.25 and DN>=GetDate()-25*365.25),
constraint FK_id_strada_S Foreign Key(id_strada)references strada(id_strada) on update
cascade,
constraint CK_tel_sportivi check (tel_sportivi like '[1-9][0-9]-[0-9][0-9]-[0-9][0-9]'),
constraint FK_id_echipa Foreign Key(id_echipa)references echipa(id_echipa) on update
cascade
)
Insert into sportivi values(1,'Teberneac',' Tatiana','09.05.1986',2,'48-20-45',1)
Insert into sportivi values(2,'Gojan',' Natalia','05.20.1987',4,'79-85-12',2)
Insert into sportivi values(3,'Gladciuc',' Marina','11.20.1987',4,'55-99-21',1)
Insert into sportivi values(4,'Liulica',' Doina','02.25.1987',5,'54-20-14',3)
Insert into sportivi values(5,'Bandalac',' Elena','04.18.1985',1,'12-45-89',2)
Insert into sportivi values(6,'Buga',' Alina','05.25.1984',3,'45-65-89',3)
Insert into sportivi values(7,'Bragaru',' Ioana','09.09.1985',5,'45-12-85',2)
Insert into sportivi values(8,'Gheorghita',' Tatiana','11.21.1986',2,'44-52-06',3)

34
1.2 Crearea şi executarea declanşatoarelor asupra bazei date
/*De creat un trigger ce nu va permite modificarea cimpului salariu antrenorilor*/

Create or alter trigger modif on Antrenor


for update
as
if update(salariu) begin
raiserror('nu puteti modifica valorile cimpului salariu',16,1)
rollback transaction
end

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

create or alter trigger inscriere on sportivi


for insert
as
declare @nr_sport int
select @nr_sport = count(id_sportivi)
from sportivi
if @nr_sport>9 begin
raiserror ('Nu e necesar de-a inscrie un nou sportiv',16,1)
rollback transaction
end

/* De creat un trigger ce permite adaugarea informatiilor(salariu antrenorilor >3000 si <2000


a)in tabela arhiva.tabela arhiva este deja creata
b)stergerea informatii(antrenorii cu salariu >3000 si <2000)*/

drop table arhiva


go
35
create table arhiva
(
id_antrenor int Not Null Primary key,
Nume varchar(20),
Prenume varchar(20),
DN smalldatetime Not Null,
tel_antrenor char(8) Not Null,
salariu int
)
begin transaction
insert into arhiva
select *
from antrenor
where salariu>3000
delete
from arhiva
where salariu<2000
commit transaction

/* De creat o tranzactie ce permite majorarea salaruiului antrenorilor cu 20%*/

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

create or alter trigger admod on antrenor for update,insert


as
declare @nr int
36
select @nr=count(*) from antrenor
where nume= (select nume from inserted) and
salariu=(select salariu from inserted)
if @nr=3 begin
raiserror ('acesta deja este',16,1)
rollback transaction
end

/* De creat un denclasator din care se va executa o procedura stocata.


In p.s vom executa numarul de antrenori*/

create or alter procedure nr_antrenor


@nr int output
as
select @nr=count(*)
from antrenor
go
create or alter trigger verif on antrenor
for insert
as
declare @n int
exec nr_antrenor @n output
if @n>10 begin
raiserror ('nu puteti angaja mai mult de 10',16,1)
rollback transaction
end

/* De creat un trigger ce nu permite adaugarea unui nou antrenor*/

Create or alter trigger antrenori on antrenor


for insert
as
declare @nr_antrenor int
37
select @nr_antrenor = count(id_antrenor)
from antrenor
if @nr_antrenor>10 begin
raiserror ('Nu e necesar de mai angaja antrenor',16,1)
rollback transaction
end

/* De creat un denclasator ce nu permite adaugarea sau modificarea unui nou sportiv


cu datele personale deja existente BD*/

create or alter trigger adau_modif on sportivi


for update,insert
as
declare @nr int
select @nr=count(*) from sportivi
where nume=(select nume from inserted) and
prenume=(select prenume from inserted) and
dn=(select dn from inserted)
if @nr=2 begin
raiserror ('acest sportiv deja exista',16,1)
rollback transaction
end

/*De creat un denclasator ce permite modificarea salariu antrenorilor


cu salariu ma mare ca 7000 numai utilizatorului ilm41*/

create or alter trigger modif_salar on antrenor


for update
as
if exists (select * from deleted where salariu>7000)
and (suser_sid()!=suser_sid('ilm42'))begin
raiserror ('modificarea salariu>7000 este permis numai utilizatorului
ilm41',16,1)
38
rollback transaction
end

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:

1. Thomas Connaly: „Baze de Date”- proiectare, implementare şi gestiune,


Teora, 2001.

2. Tutorial Ms SQL Server, an ed 2005.

3. Ms SQL Server- Book Online.

4. Mamaev „Ms SQL Server”, 2000.

40
41

S-ar putea să vă placă și