Vous êtes sur la page 1sur 29

What exactly is a trigger?

A trigger is an object contained within an SQL database that is used to execute a batch of SQL code whenever a specific event occurs. A trigger is a special set of stored procedure code whose activation is caused by modifications to the database contents. Triggers are associated with a single table, and are automatically executed internally by SQL when the data in the table is changed by either of the following statements
INSERT DELETE UPDATE
1

Syntax

Triggers in Transact-SQL

CREATE TRIGGER trigger_name BEFORE / AFTER UPDATE OR INSERT OR DELETE on table_name { FOR EACH ROW} DECLARE var Declaration BEGIN . . . body of the trigger END ;

AFTER | FOR
Specifies that the trigger is fired only when all operations specified in the triggering SQL statement have executed successfully.
2

Simple Trigger(using BEFORE)


CREATE OR REPLACE TRIGGER statement_level BEFORE UPDATE ON emp1 DECLARE vMsg VARCHAR2(30) := 'Statement Level Trigger Fired'; BEGIN dbms_output.put_line(vMsg); END statement_level; / Trigger created.
3

SQL> set serveroutput on; SQL> update emp1 2 set salary=91000 3 where emp_no=111; Statement Level Trigger Fired 1 row updated
4

SQL> CREATE OR REPLACE TRIGGER statement_level 2 AFTER UPDATE 3 ON emp1 4 DECLARE 5 vMsg VARCHAR2(30) := 'Statement Level Trigger Fired'; 6 BEGIN 7 dbms_output.put_line(vMsg); 8 END statement_level; 9 / Trigger created. SQL> update emp1 2 set salary=98000 3 where emp_no=111; Statement Level Trigger Fired 1 row updated.
5

Trigger(using AFTER)

CREATE OR REPLACE TRIGGER statement_level AFTER INSERT OR UPDATE OR DELETE ON EMP1 DECLARE vMsg VARCHAR2(30) := 'Statement Level Trigger Fired'; BEGIN IF INSERTING THEN dbms_output.put_line(vMsg || ' When Inserting'); ELSIF UPDATING THEN dbms_output.put_line(vMsg || ' When Updating'); ELSIF DELETING THEN dbms_output.put_line(vMsg || ' When Deleting'); END IF; END; / Trigger created.
6

Output:
SQL> select * from emp1; EMP_NO SALARY DEP_NO BDATE ---------- ---------- ---------- --------101 88000 30 02-MAY-88 102 82000 20 02-MAY-88 103 30000 30 02-MAY-88 104 23000 10 02-MAY-88 105 90000 20 02-MAY-88 106 86000 30 02-MAY-88 107 30000 10 04-JUN-77 108 88000 30 02-JUN-77 111 98000 30 01-AUG-09
9 rows selected.

SQL> update emp1 2 set salary=68000 3 where emp_no=110; Statement Level Trigger Fired When Updating 0 rows updated. SQL> insert into emp1 2 values(112,97000,30,'12-jan-82'); Statement Level Trigger Fired When Inserting 1 row created. SQL> delete from emp1 2 where emp_no=108; Statement Level Trigger Fired When Deleting 1 row deleted.
8

CREATE OR REPLACE TRIGGER Print_salary_changes BEFORE DELETE OR INSERT OR UPDATE on emp1 FOR EACH ROW when(new.emp_no >0) declare sal integer; begin sal:= :new.salary - :old.salary; dbms_output.put('Old salary: ' || :old.salary); dbms_output.put(' New salary: ' || :new.salary); dbms_output.put_line(' Difference ' || sal); end; / Trigger created.
9

2nd example

OUTPUT SQL> set serveroutput on; SQL> update emp1 2 set salary=92000 3 where emp_no=101; Old salary: 88000 New salary: 92000 Difference 4000 1 row updated.
10

3rd Example:
CREATE OR REPLACE TRIGGER Print_salary_changes BEFORE DELETE OR INSERT OR UPDATE on emp1 FOR EACH ROW declare no integer; begin no :=:new.dep_no; if no>20 then dbms_output.put_line('Only 40 department are present'); end if; end; /
Trigger created.
11

OUTPUT
SQL> insert into emp1 2 values(119,59000,40,'12-sep-87'); Only 40 department are present 1 row created.

12

Roll_back trigger action:



SQL> CREATE OR REPLACE TRIGGER Print_salary_changes 2 BEFORE DELETE OR INSERT OR UPDATE 3 on emp1 4 FOR EACH ROW 5 declare no integer; 6 begin 7 no :=:new.dep_no; 8 if no>40 then 9 RAISE_APPLICATION_ERROR(-20000,'only 40 department are present '); 10 end if; 11 end; 12 / Trigger created.
SQL> insert into emp1 2 values(121,89000,50,'27-sep-12'); insert into emp1 ERROR at line 1: ORA-20000: only 40 department are present ORA-06512: at "USER1.PRINT_SALARY_CHANGES", line 5

13

SQL> update emp1 2 set salary=58000 3 where emp_no=119; Old salary: 59000 New salary: 58000 Difference -1000 Statement Level Trigger Fired When Updating 1 row updated. Syntax: Alter trigger <trigger_name> (disableanable); SQL> alter trigger statement_level disable; Trigger altered. SQL> update emp1 2 set salary=58000 3 where emp_no=119; Old salary: 58000 New salary: 58000 Difference 0 1 row updated.
14

Disabling triggers:

Definition Of CURSOR
For every SQL statement execution certain area in memory is allocated. PL/SQL allow you to name this area. This private SQL area is called context area or cursor. When you declare a cursor, you get a pointer variable, which does not point any thing. When the cursor is opened, memory is allocated and the cursor structure is created. The cursor variable now points the cursor. When the cursor is closed the memory allocated for the cursor is released.

15

Cursors allow the programmer to retrieve data from a table and perform actions on that data one row at a time. There are two types of cursors implicit cursors and explicit cursors.
Implicit cursors: Implicit cursors are simple SELECT statements and are written in the BEGIN block (executable section) of the PL/SQL. Implicit cursors are easy to code, and they retrieve exactly one row. explicit cursors. Explicit cursors are used in queries that return multiple rows. The set of rows fetched by a query is called active set. The size of the active set meets the search criteria in the select statement. Explicit cursor is declared in the DECLARE section of PL/SQL program.

16

declare eno integer; esal number(10); begin select emp_no,salary INTO eno,esal from emp1 where emp_no=&emp_no; dbms_output.put_line('Number='||eno); dbms_output.put_line('salary= '||esal); end; / Enter value for emp_no: 101 old 6: where emp_no=&emp_no; new 6: where emp_no=101; Number=101 salary= 92000 PL/SQL procedure successfully completed.
17

Example for implicit Cursor

Syntax for explicit cursor Syntax:

CURSOR <cursor-name> IS <select statement>


Sample Code: DECLARE CURSOR emp_cur IS SELECT ename FROM EMP; BEGIN -----END;
18

Processing multiple rows is similar to file processing. For processing a file you need to open it, process records and then close. Similarly user-defined explicit cursor needs to be opened, before reading the rows, after which it is closed. Like how file pointer marks current position in file processing, cursor marks the current position in the active set. Opening Cursor Syntax: OPEN <cursor-name>;
Example : OPEN emp_cur; When a cursor is opened the active set is determined, the rows satisfying the where clause in the select statement are added to the active set. A pointer is established and points to the first row in the active 19 set.

Fetch statement
To get the next row from the cursor we need to use fetch statement. Syntax: FETCH <cursor-name> INTO <variables>;

Example: FETCH emp_cur INTO ena;

FETCH statement retrieves one row at a time.

20

Closing Cursor
After retrieving all the rows from active set the cursor should be closed. Resources allocated for the cursor are now freed. Once the cursor is closed the execution of fetch statement will lead to errors. CLOSE <cursor-name>;

21

Explicit Cursor Attributes


Every cursor defined by the user has 4 attributes. When appended to the cursor name these attributes let the user access useful information about the execution of a multirow query. The attributes are: %NOTFOUND: It is a Boolean attribute, which evaluates to true, if the last fetch failed. i.e. when there are no rows left in the cursor to fetch. %FOUND: Boolean variable, which evaluates to true if the last fetch, succeeded. %ROWCOUNT: Its a numeric attribute, which returns number of rows fetched by the cursor so far. %ISOPEN: A Boolean variable, which evaluates to true if the cursor is opened otherwise to false. %TYPE : is used to declare a field with the same type as -- that of a specified table's column %ROWTYPE : is used to declare a record with the same types as -found in the specified database table, view or cursor:

22

declare eno emp1.emp_no%type; esal emp1.salary%type; cursor c1 IS select emp_no,salary from emp1; begin open c1; fetch c1 into eno,esal; dbms_output.put_line(eno||'salary is $'||esal); fetch c1 into eno,esal; dbms_output.put_line(eno||'salary is $'||esal); fetch c1 into eno,esal; dbms_output.put_line(eno||'salary is $'||esal); close c1; end; / 101salary is $92000 102salary is $82000 103salary is $30000 PL/SQL procedure successfully completed.
23

Example for explicit cursor

declare eno varchar2(20); esal number(10); cursor c1 IS select emp_no,salary from emp1 order by salary desc; begin open c1; if c1%isopen then loop fetch c1 into eno ,esal; exit when c1%notfound; dbms_output.put_line(eno||' '||esal); end loop; end if; end; /

2nd Example:

24

OUTPUT
111 114 112 101 105 117 106 102 118 115 119 116 103 107 104 99000 97000 97000 92000 90000 88000 86000 82000 78000 77000 59000 57000 30000 30000 23000

PL/SQL procedure successfully completed.

25

SQL> DECLARE 2 CURSOR c1 IS 3 SELECT emp_no,salary from emp1 4 where emp_no=120; 5 employee_rec c1%ROWTYPE; 6 BEGIN 7 OPEN c1; 8 FETCH c1 INTO employee_rec; 9 DBMS_OUTPUT.PUT_LINE('Employee no: '||employee_rec.emp_no); 10 DBMS_OUTPUT.PUT_LINE('Employee salary: '||employee_rec.salary); 11 END; 12 / Employee no: 120 Employee salary: 99000 PL/SQL procedure successfully completed.

26

SQL> DECLARE 2 CURSOR c1 IS 3 SELECT emp_no,salary from emp1; 4 employee_rec c1%ROWTYPE; 5 BEGIN 6 OPEN c1; 7 FETCH c1 INTO employee_rec; 8 DBMS_OUTPUT.PUT_LINE('Employee no: ||employee_rec.emp_no); 9 DBMS_OUTPUT.PUT_LINE('Employee salary: '||employee_rec.salary); 10 END; 11 / Employee no: 101 Employee salary: 79000 PL/SQL procedure successfully completed.

27

The %ROWTYPE attribute lets you declare a record that represents a row of a database table or view. declare emp_rec emp1%rowtype; cursor c1 IS select * from emp1; begin open c1; fetch c1 INTO emp_rec; while c1%found loop dbms_output.put_line(emp_rec.bdate); fetch c1 into emp_rec; end loop; close c1; end; /
28

Use of %found arg

SQL> DECLARE 2 CURSOR c1 is 3 SELECT emp_no,salary,dep_no from emp1 4 ORDER BY salary DESC; 5 my_no emp1.emp_no%TYPE; 6 my_depno emp1.dep_no%TYPE; 7 my_sal emp1.salary%TYPE; 8 BEGIN 9 OPEN c1; 10 LOOP 11 fetch c1 into my_no, my_depno, my_sal; 12 EXIT WHEN (c1%ROWCOUNT > 5); 13 dbms_output.put_line('Employee no ' || my_no || ' (' || my_depno|| ') makes ' || my_sal); 14 END LOOP; 15 CLOSE c1; 16 END; 17 / Employee no 120 (99000) makes 30 Employee no 114 (97000) makes 40 Employee no 112 (97000) makes 40 Employee no 111 (91000) makes 30 29 Employee no 105 (90000) makes 20