Sie sind auf Seite 1von 96

Oracle 9i Database Server

PL/SQL
Procedural Language/Structured Query
Language

•PL/SQL is the procedural extension to SQL


with design features of programming
languages.
•Data manipulation and query statements of
SQL are included within procedural units of
code.
PL/SQL Environment

PL/SQL engine
PL/SQL Procedural
PL/SQL PL/SQL statement
block block SQL
executor

SQL statement executor

Oracle server
PL/SQL Block Structure

DECLARE (Optional)
Variables, cursors, user-defined exceptions
BEGIN (Mandatory)
– SQL statements
– PL/SQL statements
EXCEPTION (Optional)
Actions to perform when errors occur
END; (Mandatory)


DECLARE


BEGIN


EXCEPTION

END;
Variables
Variables are used to store values/data, for
reusability, ease of maintenance using type
attributes.
Types of Variables
•PL/SQL variables:
–Scalar
–Composite
–Reference
–LOB (large objects)

•Non-PL/SQL variables: Bind and host variables


Types of Variables
•Scalar data types hold a single value (correspond to
column types in Oracle server tables). PL/SQL also
supports Boolean variables.
•Composite data types, such as records, allow groups
of fields to be defined.
•Reference data types hold values, called pointers, that
designate other program items.
•LOB data types hold values, called locators, that
specify the location of large objects (such as graphic
images) that are stored out of line.
•Non-PL/SQL variables include host language variables
declared in precompiler programs, screen fields in Forms
applications, and SQL*Plus/iSQL*Plus host variables.
Declaring PL/SQL Variables

Syntax :
identifier [CONSTANT]* datatype [NOT NULL]*
[:= | DEFAULT expr];
* value must be assigned while declaring

Example :
DECLARE
v_hiredate DATE;
v_deptno NUMBER(2) NOT NULL := 10;
v_location VARCHAR2(13) := 'Atlanta';
c_comm CONSTANT NUMBER := 1400;
v_mgr NUMBER(6) DEFAULT 100;

The names of the variables must not be longer than 30


characters.
Adopt a naming convention for PL/SQL identifiers:
for example, v_variablename
User-Defined Subtypes
PL/SQL predefines several subtypes in package STANDARD.
For example, PL/SQL predefines the subtypes CHARACTER
and INTEGER as follows:
SUBTYPE CHARACTER IS CHAR;
SUBTYPE INTEGER IS NUMBER(38,0);
Defining Subtypes
SUBTYPE subtype_name IS base_type[(constraint)] [NOT
NULL];
DBMS_OUTPUT Package

Package DBMS_OUTPUT enables you to display output from


PL/SQL blocks and subprograms.
The procedure put_line outputs information to a buffer in the
SGA. You display the information by setting
SERVEROUTPUT ON in SQL*Plus.
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 DBMS_OUTPUT.PUT_LINE(‘Hello World');
3 END;
4 /
Hello World

PL/SQL procedure successfully completed.


PL/SQL Control Structures
IF-THEN Statement IF-THEN-ELSIF Statement

IF condition THEN
sequence_of_statements; IF condition1 THEN
END IF; sequence_of_statements1
ELSIF condition2 THEN
IF-THEN-ELSE Statement
sequence_of_statements2
IF condition THEN ELSE
sequence_of_statements1; sequence_of_statements3
ELSE END IF;
sequence_of_statements2;
END IF;
CASE Statement
[<<label_name>>]
CASE selector
WHEN expression1 THEN sequence_of_statements1;
...
WHEN expressionN THEN sequence_of_statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];

DECLARE
grade CHAR:=&grade;
BEGIN
CASE grade
WHEN ’A’ THEN dbms_output.put_line(’Excellent’);
WHEN ’B’ THEN dbms_output.put_line(’Very Good’);
WHEN ’C’ THEN dbms_output.put_line(’Good’);
WHEN ’D’ THEN dbms_output.put_line(’Fair’);
ELSE dbms_output.put_line(’No such grade’);
END CASE;
END;
Searched CASE Statement
[<<label_name>>]
CASE
WHEN search_condition1 THEN statements1;
...
WHEN search_conditionN THEN statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE [label_name];

DECLARE
grade CHAR:=&grade;
BEGIN
CASE
WHEN grade=’A’ THEN dbms_output.put_line(’Excellent’);
WHEN grade=’B’ THEN dbms_output.put_line(’Very
Good’);
WHEN grade=’C’ THEN dbms_output.put_line(’Good’);
WHEN grade=’D’ THEN dbms_output.put_line(’Fair’);
ELSE dbms_output.put_line(’No such grade’);
END CASE;
Iterative Control: LOOP and EXIT Statements
There are three forms of LOOP statements: LOOP, WHILE-
LOOP, and FOR-LOOP.

LOOP
LOOP
sequence_of_statements;
END LOOP;

use an EXIT / EXIT WHEN statement to complete the loop.


WHILE-LOOP
WHILE condition LOOP
sequence_of_statements
END LOOP;
FOR-LOOP

FOR counter IN [REVERSE] lower_bound..higher_bound


LOOP
sequence_of_statements
END LOOP;
NULL Statement
The NULL statement does nothing other than pass control to
the next statement.
Interacting with the Oracle Server

SELECT .. INTO .. Statement


-retrieves data from one or more database tables, then assigns
the selected values to variables

*To be explained with example


SQL *PLUS BIND VARIABLES

These are host variables that may be used to pass runtime


values into or out of PL/SQL block.
Bind variables are declared in SQL *PLUS

VARIABLE variable_name [NUMBER | CHAR | CHAR(N) |


VARCHAR2(N)]
Ex: VARIABLE emplname VARCHAR2(12)

*To be explained with example with PRINT command


Declaring Variables based on database columns
DECLARE
empname EMP.ENAME%TYPE;
….
%TYPE attribute enables you to define a variable based on a
table column datatype
% is attribute indicator.
PL/SQL Record Variables
A record is a group of related data items stored in fields, each
with its own name and datatype.
These items are logically related but dissimilar in type.
A record containing a field for each item lets you treat the data
as a logical unit.
To create records, you define a RECORD type, then declare
records of that type.
PL/SQL Record Structure

Field1 (data type) Field2 (data type) Field3 (data type)

Example:

Field1 (data type) Field2 (data type) Field3 (data type)


dept_id number(2) dept_name
varchar2(14) dept_loc varchar2(13)
10 ACCOUNTING NEW YOR
Syntax
TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
identifier type_name;

field_name {field_type | variable%TYPE


| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]

Note : RECORD types cannot be CREATEd and stored in the


database.
You can use %TYPE and %ROWTYPE to specify field types.
In the following example, you define a RECORD type named
DeptRec:
TYPE DeptRectype IS RECORD (
dept_id dept.deptno%TYPE, dept_name VARCHAR2(14),
dept_loc VARCHAR2(13));
Declaring a record variable
dept_rec deptrectype;

To access individual fields


dept_rec.dept_id;
dept_rec.dept_name;
*example on recordtype

Record variables based on tables


It means that each field in the record has the same name and
datatype as the columns in the specified table.
%ROWTYPE attribute is used to facilitate the declaration of a
record based on a table.
emprec EMP%ROWTYPE;
* example on rowtype
* Retired employees example.
PL/SQL Error Handling
In PL/SQL, a warning or error condition is called an
exception.
An exception is an identifier in PL/SQL that is raised during
the execution of a block that terminates its main body of
actions. A block always terminates when PL/SQL raises an
exception, but can you specify an exception handler to
perform final actions.
Examples of internally defined exceptions include no data
found, fetching multiple rows, value error, division by zero,
out of memory and many more.
For example, if the error ORA-01403 occurs when no
rows are retrieved from the database in a SELECT
statement, then PL/SQL raises the exception
NO_DATA_FOUND.
Predefined Exception raised when…
Handling Exceptions
Trap the exception Propagate the exception

DECLARE DECLARE

BEGIN BEGIN
Exception Exception
is raised is raised
EXCEPTION EXCEPTION

Exception Exception
is trapped END; END; is not
trapped
Exception
propagates to calling
environment
Predefined Exception Handler
*Examples to be given for
no_data_found,too_many_rows,value_error
OTHERS EXCEPTION HANDLER
Can be used as a generic exception handler.
SQLCODE & SQLERRM Functions
SQLCODE returns the number of the Oracle error for
internal exceptions. You can pass an error number to
SQLERRM, which then returns the message associated with
the error number.

USER-DEFINED EXCEPTIONS
PL/SQL lets you define exceptions of your own.
User-defined exceptions must be declared and must be
raised explicitly by RAISE statements.
How PL/SQL Exceptions Propagate
Procedure RAISE_APPLICATION_ERROR
The procedure RAISE_APPLICATION_ERROR lets you
issue user-defined ORAerror messages from stored
subprograms. That way, you can report errors to your
application and avoid returning unhandled exceptions.
raise_application_error(error_number, message[, {TRUE
| FALSE}]);
error_number is a negative integer in the range -20000
.. -20999
message is a character string up to 2048 bytes long.
If TRUE, the error is placed on the stack of previous
errors.
If FALSE (the default), the error replaces all previous
errors.
RAISE_APPLICATION_ERROR is part of package
DBMS_STANDARD, and as with package STANDARD, you
do not need to qualify references to it.
An application can call raise_application_error only from
an executing stored subprogram (or method).
When called, raise_application_error ends the
subprogram and returns a user-defined error number and
message to the application.
The error number and message can be trapped like any
Oracle error.
*will be discussed in procedures and triggers topic
Nonpredefined Error
PRAGMA EXCEPTION_INIT
Apart from predefined exception, we can extend the list of exceptions
associated with an Oracle error within our PL/SQL code with the use
of PRAGMA EXCEPTION_INIT keyword.
EXCEPTION PRAGMA is used to associate a named exception with a
particular Oracle error.
This enable us to trap the error specifically, rather than via an
OTHERS handle.
Only one user defined exception can be associated with one Oracle
error with each occurrence of PRAGMA EXCEPTION_INIT.

This statement is a compiler directive that allows the developer to


declare the Oracle-numbered error to be associated with a named
exception in the block.
CURSOR’s
Whenever you issue a SQL statement, the Oracle
server opens an area of memory in which the command
is parsed and executed. This area is called a cursor.
PL/SQL cursors provide a way for your program to
select multiple rows of data from the database and
then to process each row individually.
PL/SQL uses two types of cursors: implicit and explicit.

PL/SQL declares a cursor implicitly for all SQL DML


statements, including select queries that return only
one row.

However, for queries that return more than one row,


you must declare an explicit cursor.
Controlling Explicit Cursors
No

Yes
DECLARE OPEN FETCH EMPTY? CLOSE

• Create a • Identify • Load the • Test for • Release


named the active current existing the active
SQL area set row into rows set
variables • Return to
FETCH if
rows are
found
Declaring a Cursor
When you declare a cursor, you name it and associate it
with a specific query

CURSOR cursor_name [(parameter[, parameter]...)]


[RETURN return_type] IS select_statement;

where return_type must represent a record or a row in a


database table.

At this stage, the query is parsed (cols, tables etc., are


validated) but it is not executed.

Ex:
cursor emp_cur is
select ename,sal,hiredate,deptno from emp where
deptno=20;
OPENing the Cursor
Opening the cursor executes the query and identifies the
result set, which consists of all rows that meet the query
search criteria.
For cursors declared using the FOR UPDATE clause, the
OPEN statement also locks those rows.
OPEN cursor_name;
Ex:OPEN emp_cur;
OPEN c1(emplname, 3000);
OPEN c1(‘SMITH’, 1500);
OPEN c1(emplname, esal);
Fetching with a Cursor
The FETCH statement retrieves the rows in the result set
one at a time. Each fetch retrieves the current row and
then advances the cursor to the next row in the result
set.
FETCH cursor_name INTO var1,var2,.. or record_list;
Ex:
FETCH c1 INTO my_empno, my_ename, my_deptno;

LOOP
FETCH c1 INTO my_record;
EXIT WHEN c1%NOTFOUND;
-- process data record
END LOOP;
Closing a Cursor
The CLOSE statement disables the cursor, and the result
set becomes undefined.
Once a cursor is closed, you can reopen it. Any other
operation on a closed cursor raises the predefined
exception INVALID_CURSOR.

CLOSE cursor_name;
Ex:
CLOSE emp_cur;
CURSOR attributes
Cursor attributes return information about the execution
of a multi-row query.
%FOUND Attribute: Has a Row Been Fetched?- equates to
TRUE if the last fetch returned a row, or FALSE if the last
fetch failed to return a row.
%ISOPEN Attribute: Is the Cursor Open? - equates to TRUE
if explicit cursor is open; otherwise, %ISOPEN equates to
FALSE. In case of implicit cursors always it equates to
FALSE.
%NOTFOUND Attribute: Has a Fetch Failed? - yields FALSE if
the last fetch returned a row, or TRUE if the last fetch
failed to return a row.
%ROWCOUNT Attribute: How Many Rows Fetched So Far?
yields the number of rows fetched so far. The number is
incremented if the last fetch returned a row.
Examples to be discussed:

• To fetch empno,ename,job,sal,deptno from emp using


record type variable using cursor%ROWTYPE
• To fetch top five employee details.
• To fetch nth row from a table
CURSOR FOR loop:
PL/SQL provides a special kind of FOR loop to process the
rows returned in an explicit CURSOR.
In a CURSOR FOR loop, a declared CURSOR is OPENed,
FETCHed from and CLOSEed automatically when all of the
rows have be processed.
Each iteration of the loop fetches a row from the active set into
a record, which is implicitly declared for use within the loop.
The loop is terminated automatically at the end of the iteration
when the last row was FETCHed.
Example using CURSOR FOR LOOP
SET SERVEROUTPUT ON

DECLARE
TYPE emp_tabtype IS TABLE OF EMP%ROWTYPE INDEX BY
BINARY_INTEGER;
EMPREC emp_tabtype;

BEGIN

for rec in (select * from emp) loop


EMPREC(rec.empno):=rec;
END LOOP;

for i in EMPREC.FIRST..EMPREC.LAST LOOP


if EMPREC.exists(i) then
dbms_output.put_line(i||','||EMPREC(i).ENAME);
end if;
end loop;
END;
PL/SQL Subprograms

Subprograms are named PL/SQL blocks that can take


parameters and be invoked.
PL/SQL has two types of subprograms called procedures and
functions.
Procedures are used to perform an action
Functions are used to compute a value.
subprograms have a declarative part, an executable part, and
an optional exception-handling part.
The declarative part contains declarations of types, cursors,
constants, variables, exceptions, and nested subprograms.
Advantages of Subprograms

Extensibility: that is, they let you tailor the PL/SQL language
to suit your needs.
Modularity: that is, they let you break a program down into
manageable, well-defined modules.
reusability and maintainability: Once validated, a subprogram
can be used with confidence in any number of applications. If
its definition changes, only the subprogram is affected. This
simplifies maintenance.
Abstraction: To use subprograms, you must know what they
do, not how they work.
PL/SQL Procedures
Syntax:

[CREATE [OR REPLACE]]


PROCEDURE procedure_name[(parameter[,
parameter]...)]
{IS | AS}
[local declarations]
BEGIN
executable statements
[EXCEPTION
exception handlers]
END [procedure_name];

First 2 lines are procedure specification and rest is


procedure body
•declarative part is placed between the IS and BEGIN
•keyword DECLARE is not used.
•Procedures that take no parameters are written without
parentheses.
•You cannot constrain the datatype of a parameter.
PROCEDURE reconcile (acct_id CHAR(5)) IS ... illegal
However, you can use the following workaround to size-
constrain parameter types indirectly:
DECLARE
SUBTYPE Char5 IS CHAR(5);
PROCEDURE reconcile (acct_id Char5) IS ...
where parameter stands for the following syntax:
parameter_name [IN | OUT | IN OUT ] datatype [{:= |
DEFAULT} expression]
Procedural Parameter Modes
Procedure
IN parameter
Calling
environment OUT parameter
IN OUT parameter

procedure …

BEGIN

EXCEPTION

END;
A simple PL/SQL procedure
To increase the salary of employee
CREATE OR REPLACE PROCEDURE raise_salary (emp_id
INTEGER, increase REAL) is
BEGIN
UPDATE emp SET sal = sal + increase
WHERE empno = emp_id;
commit;
END raise_salary;
Calling a procedure
SQL> EXECUTE RAISE_SALARY(7369,100);
SQL> begin
2 raise_salary(7369,100);
3 end;
4 /
CREATE PROCEDURE calc_bonus (emp_id IN
emp.empno%TYPE, bonus OUT REAL) IS
BEGIN
SELECT sal * 3 INTO bonus FROM emp WHERE
empno = emp_id;
END;

Calling procedure from a PL/SQL block


DECLARE
empid emp.empno%TYPE:=&EMPNO;
bonus NUMBER;
BEGIN
calc_bonus(empid,bonus);
dbms_output.put_line('Bonus='||bonus);
END;
Default Values for Subprogram Parameters

PROCEDURE create_dept (dno dept.deptno%type,


new_dname dept.dname%type DEFAULT ’TEMP’,
new_loc dept.loc%type VARCHAR2 DEFAULT ’TEMP’) IS
BEGIN
INSERT INTO dept
VALUES (dno, new_dname, new_loc);
Commit;
END;

If an actual parameter is not passed, the default value of


its corresponding formal parameter is used.

create_dept;
create_dept(’MARKETING’);
create_dept(’MARKETING’, ’NEW YORK’);
you cannot skip a formal parameter by leaving out its
actual parameter.
create_dept(‘NEW YORK’); -- incorrect
You cannot solve the problem by leaving a placeholder for
the actual parameter.
create_dept(, ’NEW YORK’); -- not allowed
In such cases, you must use named notation, as follows:
create_dept(new_loc => ’NEW YORK’);
Dropping Procedures

DROP PROCEDURE procedure_name;


PL/SQL Functions

Functions and procedures are structured alike, except


that functions have a RETURN clause.
[CREATE [OR REPLACE ] ]
FUNCTION function_name [ ( parameter [ , parameter ]...
) ] RETURN datatype
{IS | AS}
[ local declarations ]
BEGIN
executable statements;
RETURN Statement;
[ EXCEPTION
exception handlers ]
END [ function_name ];
RETURN Statement
RETURN statement must contain an expression, which is
evaluated when the RETURN statement is executed.
In a function, there must be at least one execution path
that leads to a RETURN statement. Otherwise, you get a
function returned without value error at run time.
Examples :
A function which returns string in sentence case after
accepting a string

CREATE OR REPLACE FUNCTION SENTCASE(STR


VARCHAR2)
RETURN VARCHAR2
IS
S VARCHAR2(80);
BEGIN
S:=UPPER(SUBSTR(STR,1,1))||
LOWER(SUBSTR(STR,2));
RETURN S;
END;
Calling a function
SELECT SENT_CASE('HOW are YOU now') FROM
DUAL;
Examples:
Function to get day of the week.
Function to calculate your age in years and months
Function to retrieve emprecord with max salary.

Dropping Functions
DROP FUNCTION function_name
Comparing Procedures
and Functions
Procedures Functions
Execute as a PL/SQL Invoke as part of an
statement expression
Do not contain RETURN Must contain a RETURN
clause in the header clause in the header
Can return none, one, Must return a single value
or many values
Can contain a RETURN Must contain at least one
statement RETURN statement
Overview of Packages

Packages:
•Group logically related PL/SQL types, items,
and subprograms
•Consist of two parts:
–Specification
–Body
•Cannot be invoked, parameterized, or nested
•Allow the Oracle server to read multiple
objects into memory at once
Components of a Package
Public variable
Package
specification Procedure A
Public procedure
declaration

Private variable
Procedure B Private procedure
Package definition
body
Procedure A Public procedure
definition
Local variable

Note : A package specification can exist without a package


body, but a package body cannot exist without a package
specification.
Packages usually have two parts, a specification and a body,
although sometimes the body is unnecessary.

The specification is the interface to your applications; it


declares the types, variables, constants, exceptions, cursors,
and subprograms available for use.

The body fully defines cursors and subprograms, and so


implements the spec.
Package Specification

Package Body
Package for handling employees

CREATE OR REPLACE PACKAGE emp_actions AS


PROCEDURE hire_employee (
empno NUMBER,
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER);
PROCEDURE fire_employee (emp_id NUMBER);
PROCEDURE raise_salary (emp_id INTEGER, increase
NUMBER);
END emp_actions;
Package body
CREATE OR REPLACE PACKAGE BODY emp_actions AS
PROCEDURE hire_employee (
empno NUMBER,
ename VARCHAR2,
job VARCHAR2,
mgr NUMBER,
sal NUMBER,
comm NUMBER,
deptno NUMBER) IS
BEGIN
INSERT INTO emp VALUES (empno, ename, job, mgr,
SYSDATE, sal, comm, deptno);
END hire_employee;
(cont’d)
Package body cont’d…
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;

PROCEDURE raise_salary (emp_id INTEGER, increase


NUMBER) IS
BEGIN
UPDATE emp SET sal = sal + increase WHERE empno =
emp_id;
END raise_salary;
END emp_actions;
Executing Packages
-EXECUTE EMP_ACTIONS.FIRE_EMPLOYEE(7566);
-EXECUTE EMP_ACTIONS.HIRE_EMPLOYEE
(1000,'RAJESH','MANAGER',7566,3000,500,10);
-EXECUTE EMP_ACTIONS.RAISE_SALARY(7369,100);
Using cursors in a package
CREATE PACKAGE emp_stuff AS
CURSOR c1 RETURN emp%ROWTYPE;
END emp_stuff;

CREATE PACKAGE BODY emp_stuff AS


CURSOR c1 RETURN emp%ROWTYPE IS
SELECT * FROM emp WHERE sal > 2500;
END emp_stuff;
(cont’d …..)
Using cursor in a PL/SQL block

DECLARE
emp_rec emp%ROWTYPE;
BEGIN
OPEN emp_stuff.c1;
LOOP
FETCH emp_stuff.c1 INTO emp_rec;
EXIT WHEN emp_stuff.c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(emp_rec.ename||','||
emp_rec.job||','||emp_rec.sal);
END LOOP;
CLOSE emp_stuff.c1;
END;
Overloading

•Enables you to use the same name for different


subprograms inside a PL/SQL block, a subprogram, or a
package

•Requires the formal parameters of the subprograms to


differ in number, order, or data type family

•Enables you to build more flexibility because a user or


application is not restricted by the specific data type or
number of formal parameters
Example :

Package Specification

CREATE OR REPLACE PACKAGE over_pack


IS
PROCEDURE add_dept
(p_deptno IN dept.deptno%TYPE,
p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown');
PROCEDURE add_dept
(p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown');
END over_pack;
/
Package Body
CREATE OR REPLACE PACKAGE BODY over_pack IS
PROCEDURE add_dept
(p_deptno IN dept.deptno%TYPE,
p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown')
IS
BEGIN
INSERT INTO dept VALUES (p_deptno, p_name, p_loc);
END add_dept;
PROCEDURE add_dept
(p_name IN dept.dname%TYPE DEFAULT 'unknown',
p_loc IN dept.loc%TYPE DEFAULT 'unknown')
IS
BEGIN
INSERT INTO dept VALUES (dept_seq.NEXTVAL, p_name,
p_loc);
END add_dept;
END over_pack;
/
-Data dictionary information about PACKAGE’s is stored in
USER_SOURCE.
-To view structure of package
-DESC <package_name>
-To drop packages
-DROP PACKAGE BODY <package_name>
-DROP PACKAGE <package_name>
TRIGGER
A trigger:
•Is a PL/SQL block or a PL/SQL procedure
associated with a table, view, schema, or the
database
•Executes implicitly whenever a particular
event takes place
USES OF TRIGGERS

Triggers may be used to


-supplement declarative referential integrity.
-enforce complex business rules.
-audit change to data.
-monitor database related actions.
Creating DML Triggers

A triggering statement contains:


•Trigger timing
–For table: BEFORE, AFTER
–For view: INSTEAD OF
•Triggering event: INSERT/UPDATE/DELETE
•Table name: On table, view
•Trigger type: Row or statement
•WHEN clause: Restricting condition
•Trigger body: PL/SQL block
DML Trigger Components

Trigger timing: When should the trigger fire?

•BEFORE: Execute the trigger body before the


triggering DML event on a table.

•AFTER: Execute the trigger body after the


triggering DML event on a table.

•INSTEAD OF: Execute the trigger body instead


of the triggering statement. This is used for
views that are not otherwise modifiable.
DML Trigger Components

Triggering user event: Which DML statement


causes the trigger to execute?
You can use any of the following:
•INSERT
•UPDATE
•DELETE
DML Trigger Components

Trigger type: Should the trigger body execute


for each row the statement affects or only
once?
•Statement: The trigger body executes once for
the triggering event. This is the default. A
statement trigger fires once, even if no rows
are affected at all.
•Row: The trigger body executes once for each
row affected by the triggering event. A row
trigger is not executed if the triggering event
affects no rows.
DML Trigger Components

Trigger body: What action should the trigger


perform?
The trigger body is a PL/SQL block or a call to a
procedure.
Syntax for Creating
DML Statement Triggers
Syntax:

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON table_name
trigger_body

Note: Trigger names must be unique with


respect to other triggers in the same schema.
Example:
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT or UPDATE or DELETE ON emp
BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR(SYSDATE,'HH24:MI')
NOT BETWEEN '08:00' AND '18:00')
THEN RAISE_APPLICATION_ERROR (-20500,
'DML allowed only during business hours.');
END IF;
END;
/
Creating a DML Row Trigger

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON table_name
[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW
[WHEN (condition)]
trigger_body
Using OLD and NEW Qualifiers

Within a ROW trigger, reference the value of a column


before and after the data change by prefixing it with the
OLD and NEW qualifier.
•The OLD and NEW qualifiers are available only in ROW
triggers.
•Prefix these qualifiers with a colon (:) in every SQL and
PL/SQL statement.
•There is no colon (:) prefix if the qualifiers are
referenced in the WHEN restricting condition.
Note: Row triggers can decrease the performance if you do
a lot of updates on larger tables.
Fires when DML is performed on EMP table

CREATE OR REPLACE TRIGGER Print_salary_changes


BEFORE INSERT OR UPDATE ON Emp
FOR EACH ROW
WHEN (new.Empno > 0)
DECLARE
sal_diff number;
BEGIN
sal_diff := :new.sal - :old.sal;
dbms_output.put_line('Old salary: ' || :old.sal);
dbms_output.put_line(' New salary: ' || :new.sal);
dbms_output.put_line(' Difference ' || sal_diff);
END;
INSTEAD OF Triggers
Application
INSERT INTO my_view
. . .;

INSERT
TABLE1
INSTEAD OF
Trigger

UPDATE
MY_VIEW TABLE2
Creating an INSTEAD OF Trigger

Syntax:
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
event1 [OR event2 OR event3]
ON view_name
[REFERENCING OLD AS old | NEW AS new]
[FOR EACH ROW]
trigger_body
INSTEAD OF Trigger Example

CREATE OR REPLACE VIEW EMPDEPT


AS
SELECT EMPNO,ENAME,JOB,SAL,E.DEPTNO,DNAME,LOC
FROM EMP E,DEPT D
WHERE E.DEPTNO=D.DEPTNO;

CREATE OR REPLACE TRIGGER INSTEADVIEW


INSTEAD OF INSERT OR UPDATE OR DELETE ON EMPDEPT
FOR EACH ROW
BEGIN
IF INSERTING THEN
INSERT INTO EMP(EMPNO,ENAME,JOB,SAL,DEPTNO)
VALUES(:NEW.EMPNO, :NEW.ENAME,:NEW.JOB,:NEW.SAL,
:NEW.DEPTNO);
INSERT INTO DEPT VALUES(:NEW.DEPTNO,:NEW.DNAME,:NEW.LOC);
ELSIF DELETING THEN
DELETE EMP WHERE DEPTNO=:OLD.DEPTNO;
DELETE DEPT WHERE DEPTNO=:OLD.DEPTNO;
END IF;
END;
Altering triggers

ALTER TRIGGER trigger_name ENABLE|DISABLE;


ALTER TABLE table_name ENABLE|DISABLE all
triggers;
Dropping triggers:
DROP TRIGGER trigger_name;
The following data dictionary views reveal
information about triggers:
- USER_TRIGGERS

Das könnte Ihnen auch gefallen