add

About Me

My photo
Oracle Apps - Techno Functional consultant

Sunday, October 30

Triggers in Oracle

 Database Triggers:
 - A set of pl/sql statements stored permenantly in    database and "automatically" activated when ever    an event raising statement ( DML ) is executed.
 - They are stored in "User_Triggers" system table.
 - They r used to impose Business rules / user        defined restrictions on Table.
 - They r also activated when Tables are     manipulated by other users or by other application   s/w tools.
 - They provide high security on tables.

 Trigger Parts:  4 Parts
 1. Triggering Event : Indicates when to activate the       trigger .    
Before  -- insert / update / delete
After   --  insert / update / delete 

 2. Trigger Types: 2 Types
 i) Row Triggers : Activates the trigger for every      row manipulated by DML statement.
 ii) Statement Triggers: Activates the trigger for        only once  for 1 DML statement ( Default Type )

 3. Trigger Restriction:
  Used to stop the activation of trigger based on     condition.  If condition is True trigger is active.

 4. Trigger Body: A set of pl/sql statements

 Syntax:
 Create or replace Trigger < Trigger name >
 before/after insert or update or delete 
 [ of <columns> ] on < Table name >
 [ for each row
 when (< condition >) * if condition is True trigger                                         is  executed
 declare                                  
   < variable declaration >; ]
 begin
   < exec stmts >;
 [ exception
   <exec stmts >; ]
 end;
---------------------------------------------------------------
* Trigger converts student name to upper case        automatically. create or replace Trigger up_con
 before insert on stu_info
 for each row
 begin
  :new.sname = upper(:new.sname);
 end;

 insert into stu_info    values(101,'ram','ORACLE',2500);
 >select * from stu_info;
   101  RAM  ORACLE  2500
---------------------------------------------------------------  
New & Old (Pseudo Columns):-------------------------------------
 Used to retrieve data from DML stmt temporary   buffer.  * valid with "ROW" triggers only.

    INSERT   UPDATE    DELETE
 NEW    valid         valid        invalid
 OLD    invalid      valid         valid

 * They r refered with : (colon) to indicate as Bind       variables.
    They r accessed from SQL buffer to Pl/sql block.
---------------------------------------------------------------
 Triggering Events: Before insert Row,  Before update Row,
 Before delete Row
 Before insert Stmt,  Before update Stmt,
 Before delete Stmt
 After insert Row,  After update Row,
 After delete Row
 After insert Stmt,  After update Stmt,
 After delete Stmt
 12 Events per Table are allowed.
---------------------------------------------------------------
 * Modifying existing trigger create or replace Trigger up_con
 before insert on stu_info
 for each row
 begin
 if :new.course = 'oracle' and :new.fee_paid = 2500  then
 :new.sname := upper(:new.sname);     * stu_info
 else                                                       ---------- 
 :new.sname := lower(:new.sname);         roll
 end if;                                                    sname
 end;                                                       course
                                                              fee_paid
 insert into stu_info   values(111,'sekhar','oracle',2500);
 insert into stu_info   values(112,'SRINATH','oracle',1000);
 select * from stu_info;
 111 SEKHAR  oracle 2500
 112 srinath oracle 1000
---------------------------------------------------------------
* Trigger Checks for valid increment on employ          salary :>create or replace trigger chk_incr
   before update of sal on emp
   for each row
   begin
   if :new.sal <= :old.sal then
   raise_application_error(-20300,' Increment must      be more  than existing salary ');
   end if;
   end;

 >update emp set sal = sal - 3000
    where empno = 7900;
 >update emp set sal = sal - sal *.35;
---------------------------------------------------------------
 Note: Column Specification [ of sal ] is supported with   UPDATE event only.  Not valid with Insert and    Delete Operations ( Row Level Operations ).

 * Raise_application_error(error no,error message); Built_in sub program stops the DML stmt execution
 and displays the error message.
 Error No Range : -20001 to -20999
 Oracle Reserved Error Nos: -20000 to +20000
---------------------------------------------------------------
 
 * Trigger checks for null value in dept name. >create or replace trigger chk_null
   before insert or update of dname on dept
   for each row
   begin
   if :new.dname is null then
   raise_application_error(-20301,
    ' Department name cannot be blank ');
  end if;
 end;

 >insert into dept values(88,null,'Hyd');
 >update dept set dname = null
   where deptno = 30;
---------------------------------------------------------------
 Note: Constraint Vs Trigger Constraints will check for existing rows also
 Triggers will not check for existing rows

 Constraints provide standard error messages
 Triggers provide user friendly error messages

 Constraints provides pre-defined rules on table   columns.
 Triggers provides user-defined rules on table   columns

* If constraint  & Trigger are defined on table at a      time only Trigger will be activated.---------------------------------------------------------------
 > Create table job_pays
   ( job varchar2(20), losal number(10),
     hisal number(10));

 insert into job_pays values
 ('CLERK' , 3000 , 10000);
 insert into job_pays values
 ('SALESMAN' , 5000 , 15000);
 insert into job_pays values
 ('MANAGER' ,  8000  , 20000);
 insert into job_pays values
 ('ANALYST' , 10000 , 30000);
 insert into job_pays values
 ('EXECUTIVE' , 10000 , 25000);

 * Trigger Checks for valid salary according to the     Job. create or replace trigger chk_sal
 before insert on emp for each row
 -- if condition is True trigger will be executed
 when (new.job <> 'PRESIDENT') 
 declare
 minpay number(10);
 maxpay number(10);
 begin
 select losal,hisal into minpay,maxpay from      job_pays where job = :new.job;
 if :new.sal < minpay or :new.sal > maxpay then
 raise_application_error(-20200,' Salary must be    between '||minpay||' and '||maxpay||' for Job    '||:new.job);
 end if;
 exception
 when no_data_found then
 raise_application_error(-20201,' No such job exists  '||:new.job);
 end;

 INSERT INTO EMP(EMPNO,ENAME,JOB,SAL)
  VALUES(&1,'&2','&3',&4);
--------------------------------------------------------------- 
* Trigger adds the increment amount automatically    to Employ salary. ( Using IMPLICIT Cursor )                   
 create or replace trigger add_incr
 before insert on incr for each row
 begin   
   update emp set sal = sal + :new.amt
   where empno = :new.empno;
     -- Using implicit cursor
   if sql%notfound then
   raise_application_error(-20111,' No such employ     exists with employ code '||:new.empno);
   end if;
   end;

 create table incr(empno number(4), amt    number(10));
 select empno,ename,sal from emp
 where empno = 7900;
 insert into incr values(7900,4000);
 select empno,ename,sal from emp
 where empno = 7900;
 insert into incr values(799,2000);
---------------------------------------------------------------  
Student        Fee_instalments
 ---------        --------------------
 roll - 101                 roll   prev_fee   curr_fee   DOP
 name - RAM        101         0            1000         ---
 course - Oracle9i 101     1000        2000        ---
 fee - 5000           101     3000        2000        ---

 * Trigger adds the fee instalment amount            automatically into fee_instalments table .
 create or replace trigger add_fee
 before insert or update on student
 for each row
 begin
 if inserting then
 insert into fee_instalments values
 (:new.roll, 0, :new.fee, sysdate);
 elsif updating then
 insert into fee_instalments values
 (:old.roll, :old.fee, :new.fee - :old.fee, sysdate);
 end if;
 end;

 insert into student     values(101,'RAM','oracle9i',1000);
 update student set fee = fee + 2000
 where roll = 101;
 update student set fee = fee + 2000
 where roll = 101;
 select * from fee_instalments;

* Keywords:  inserting, updating, deleting 
 -- Represents insert,update and delete operations
 -- Valid in Triggers only
---------------------------------------------------------------
 Transaction -- Table
 --------------
 Accno   tran_type      amt
 101    D     5000
 102    D     7500
 103        D     1000
 104         W     1000
 105         W     9000

 * Statement Level Trigger:
 * Triggers Locks the Transaction table for update        and delete operations. ( Only insert allowed )

 create or replace trigger lock_trans
 before update or delete on transaction
 begin
 raise_application_error(-20555, ' Invalid operation   on Transaction Table ');
 end;

 delete from transaction; update transaction set amt = amt + 1000;
---------------------------------------------------------------  Disabling Triggers:
 >Alter table transaction disable all triggers;
 >Alter table bankmaster disable all triggers;

 Enabling Triggers: >Alter table transaction enable all triggers;
 >Alter table bankmaster enable all triggers;

 Removing Triggers: Drop trigger < Trigger name >;
 >Drop trigger CHK_SAL;

 Checking for Existing Triggers: >desc User_triggers
 >select  trigger_name , triggering_event from
   user_triggers where table_name = 'EMP';
 >select * from user_triggers
   where trigger_name = 'CHK_SAL';
 >select text from USER_SOURCE
    where name = 'CHK_SAL';
 > desc user_source
 
 * User_source -- system table holds the details of       Triggers .---------------------------------------------------------------
 * Statement Level Trigger:
 * Trigger Locks the table for DML operations to         provide security:
 * Trigger checks for i> Valid Timings ii> Weekends
    iii> Public Holidays

 create or replace trigger security_chk
 before insert or update or delete on Bankmaster
 declare
 a number;
 begin
 -- check for valid Timings
 if to_char(sysdate,'hh24') not in     (10,11,12,13,14,15,16,17) then
 raise_application_error(-20111,' No operations     allowed -  Invalid Timings ');
 end if;
 -- check for weekends
 if to_char(sysdate,'dy') in ('sat','sun') then
 raise_application_error(-20112,' No operations     allowed -  Weekends ');
 end if;
 -- check for Public Holidays
 select count(*) into a from holiday
 where to_date(hdate) = to_date(sysdate);
 if a > 0 then
 raise_application_error(-20113,' No operations      allowed - Public Holiday ');
 end if;
 end;

 Holiday
 --------
 hdate --- '15-aug-10'            
 description --- 'Independence Day'  
---------------------------------------------------------------
* Trigger updates Transactions automatically to       Master table.

 Bankmaster        Transaction
 -------------        --------------
 accno            accno
 name                                  tran_type
 acc_type            tran_date
 curr_bal            amt
                                            
 insert into bankmaster   values(101,'RAM','S',20000);   

 create or replace trigger add_deposit
 After insert on transaction for each row
 begin
 if :new.tran_type = 'D' then
 update bankmaster set curr_bal = curr_bal +    :new.amt  where accno = :new.accno;
 end if;
 end;

 insert into transaction   values(101,'D',sysdate,10000);
 insert into transaction   values(101,'D',sysdate,30000);
 select * from bankmaster;
 101    RAM    S   60000
---------------------------------------------------------------
 Instead of Triggers: [ 8i ]
 - Triggers supported only on "views"
 * - Used to perform DML operations on Join views
 *  Instead of  --- insert, update, delete

 Ex: 1
 >create view v1 as select * from emp;

 > create trigger t1 instead of delete on v1
    for each row
 begin
 dbms_output.put_line(' Record Removed ');
 end;

 > delete from v1 where empno = 7900;
 > select * from v1 where empno = 7900;

  create trigger t2 instead of delete on v1
    for each row
 begin
 insert into del_tab    values(:old.empno,:old.ename,sysdate,user);
 end;
---------------------------------------------------------------
 
 ** Manipulating Join views thru Instead of Triggers Ex: 2
 >create view edept as select empno, ename, sal,     job, emp.deptno, dept.deptno dno, dname, loc      from emp, dept
 where emp.deptno = dept.deptno;

 > insert into edept                  values(4411,'VIJAY',20000,'MANAGER',
   99,99,'TECHNICAL','HITECH');   --- error

 >create trigger t2 instead of insert on edept
  for each row
  begin
  insert into dept          values(:new.dno,:new.dname,:new.loc);
  insert into emp(empno,ename,sal,job,deptno)         values (:new.empno,:new.ename,:new.sal,          :new.job, :new.deptno);
  end;
 /

 >insert into edept values (......);   --- repeat step 2
 >select * from edept;
---------------------------------------------------------------
 Ex : 3
 >delete from edept where deptno = 99;
 ( Removes data from emp table only - key                  preserved table )

 * Trigger Removes records from 2 tables create or replace trigger trig11
 instead of delete on edept
 for each row
 begin
 delete from emp where deptno = :old.deptno;
 delete from dept where deptno = :old.deptno;
 end;

 delete from edept where deptno = 99; ( Removes    data from emp ,dept table also )
---------------------------------------------------------------  
Invalid Triggers : 1. >create table temp1(c1 number(3),
        c2 varchar2(10));

 2. >create trigger trig1
     before insert on temp1 for each row
     begin
      insert into temp1 values(102,'SIVA');
     end;
    /

 3. >insert into temp1 values(101,'RAM');
     Error:  It leads to an infinite loop
---------------------------------------------------------------  
>create trigger trig2
   before insert on temp1 for each row
   begin
   update temp1 set c2 = 'HARI';
   end;

 >insert into temp1 values (102,'RAVI');

 It will not perform update in Trigger body becoz 2    DML operations cannot be performed on table at      once.  It leads to a " Trigger Mutuation " error   while working in other s/w tools.
---------------------------------------------------------------  
Note:
 **  TCL commands are not allowed in Triggers.
 Becoz Trigger will be executed while  performing     DML stmt but TCL has to be given after DML stmt    execution.

---------------------------------------------------------------  
Advantage of Database Triggers:  - Automatic execution of code based on event .
  - Used to impose user defined restrictions on             Tables .
  - Provides Security on Tables while Manipulating        data from any where .
---------------------------------------------------------------

No comments: