PL/SQL
Chapter 8
Outline
 Procedures
 Cursors
 Triggers
Procedural SQL
 SQL does not support the conditional execution
of procedures as well as looping operations.
 To overcome the lack of procedural functionality
in SQL and to provide standardization, SQL-99
standard defines the use of persistent stored
modules (PSM).
What is PSM?
 A PSM is a block of code containing standard SQL statements and
procedural extensions that is stored and executed at the DBMS
server.
 The PSM represents business logic that can be encapsulated,
stored and shared among multiple database users.
 Oracle implements PSMs through its procedural SQL language.
What is PL/SQL and where can PL/SQL
be used?
 Procedural SQL (PL/SQL) is a language that makes
it possible to use and store procedural code and SQL
statements within the database and merge SQL and
traditional programming constructs. The procedural
code is executed as a unit by the DBMS when it is
invoked b the end user.
 PL/SQL is used to create
 Anonymous PL/SQL blocks (without name)
 Stored Procedures
 PL/SQL functions
 Triggers
PL/SQL block
 The PL/SQL block starts with the DECLARE section in which the






variables, the data types or the initial values are declared.
The PL/SQL block ends with the word END
The PL/SQL block can be executed by typing / and press enter key.
Each statement inside the PL/SQL code must end with a semicolon “;”.
To display the output use the command dbms_output.put_line(‘any
string’);.
Conditional statement or Looping statements can be used after declare
statements;
The SELECT statement uses the INTO keyword inside the PL/SQL
block of code to assign the output of the query to a PL/SQL variable. If
the SELECT statement returns more than one value, you will get an
error.
PL/SQL Program Blocks
7
Commands included in PL/SQL
 Comments: PL/SQL program includes commands such as
Comments statements that are lines of text that explain or
document a program step or series of steps.
 Not executed by interpreter
 To create a block of comments enclosed between /* and */
 To create one line comment type two hyphens -- at the
beginning of the line.
 PL/SQL programs have
 Commands to perform arithmetic operations
 Assignment statements that assign values to variables
 Conditional structures to perform decisions
 Looping structures to repeat instructions multiple times
 SQL commands that retrieve data.
8
Procedural Statements
 Sequences
Statement 1;
Statement 2;…
 Control Statements
IF <condition>
THEN statement1;
ELSE statement2;
ENDID;
 Looping Structures
DO WHILE
LOOP….
Statement 1;
Statement 2;…
ENDLOOP
Assignment Statements
 Assigns a value to a variable
 An assignment statement has the following syntax
variable_name := value;
 Value can be a literal:
current_s_first_name := 'John';
 Value can be another variable:
current_s_first_name := s_first_name;
10
Displaying PL/SQL Program Output in
SQL*Plus
 PL/SQL output buffer
 Memory area on database server
 Stores program’s output values before they are displayed to user
 Should increase the size of the buffer as
 SET SERVEROUTPUT ON SIZE buffer_size
 Default buffer size
 2000 bytes
 To display more than just a few lines of output, it is better to
make the output buffer larger than the default size.
 Maximum is 1000000 bytes
11
Displaying PL/SQL Program Output in
SQL*Plus (continued)
 Display program output
 DBMS_OUTPUT.PUT_LINE('display_text');
 The display_text value can
 contain literal character strings such as ‘ My name is
Roohi’ or
 variable names such as current_s_first.
 Display maximum of 255 characters of text data
12
Executing a PL/SQL
Program in SQL*Plus





13
Create program in text editor
Copy and paste program commands into SQL*Plus window
Press Enter after last program command
Type front slash ( / )
Then press Enter again
Executing a PL/SQL Program in SQL*Plus
Write a PL/SQL program to display the current date as shown below
Today’s date is 27-Feb-2012
DECLARE
todays_date DATE;
X number;
BEGIN
todays_date := SYSDATE;
X:= 1;
DBMS_OUTPUT.PUT_LINE('Today''s date is ');
DBMS_OUTPUT.PUT_LINE(todays_date);
DBMS_OUTPUT.PUT_LINE(x);
END;
14
PL/SQL Data Conversion Functions
 Sometimes the PL/SQL interpreter is unable to implicitly convert
value and an error occurs.
 Other times, PL/SQL interpreter performs an implicit conversion
and produce unexpected/invalid data
 Explicit data conversions
 Convert variables to different data types using data conversion
functions that are built into PL/SQL.
15
A Guide to Oracle10g
Display today’s date using concatenated
character string
 To concatenate two strings in PL/SQL, you use the double bar (||)
operator:
new_string := string1 || string2;
SQL>
2
3
4
5
is
6
7
DECLARE
todays_date DATE;
BEGIN
todays_date :=SYSDATE;
DBMS_OUTPUT.PUT_LINE('Today''s date
' || TO_CHAR(todays_date));
END;
/
PL/SQL procedure successfully completed.
16
PL/SQL Decision Control Structures
 Use IF/THEN/ELSE to execute code if condition is true or
FALSE
 IF condition THEN
commands that execute if condition is TRUE;
ELSE
commands that execute if condition is
FALSE;
END IF;
 Evaluates ELSE commands if condition is FALSE
17
PL/SQL Decision Control Structures
 Use IF/ELSIF decision control structure to test for
many different conditions.:
 IF condition1 THEN
commands that execute
ELSIF condition2 THEN
commands that execute
ELSIF condition3 THEN
commands that execute
...
ELSE
commands that execute
conditions are TRUE;
END IF;
18
if condition1 is TRUE;
if condition2 is TRUE;
if condition3 is TRUE;
if none of the
Loops
 PL/SQL has 5 loop structures
 LOOP…EXIT WHEN
 WHILE …..LOOP
 Numeric FOR loops
19
The LOOP...EXIT WHEN Loop
The LOOP…EXITWHEN loop can also be
either a pretest or a post test loop.
LOOP
program statements
EXIT WHEN condition;
END LOOP;
20
The WHILE...LOOP
The WHILE….LOOP is a pretest loop that evaluates the exit
condition before it executes any program statement.
WHILE condition LOOP
program statements
END LOOP;
21
The Numeric FOR Loop
 Does not require explicit counter increment
 The loop counter variable and it start and end values are declared in the
loop’s FOR statement.
 Automatically increments counter variable until it reaches the end value.
FOR counter_variable IN start_value ..
end_value
LOOP
program statements
END LOOP;
22
Using SQL Queries in PL/SQL
Programs
 Action queries can be used as in SQL*Plus
 May use variables in action queries
 DDL commands may not be used in PL/SQL
23
Using SQL Commands in PL/SQL
Programs
24
PL/SQL block to insert a new row in the
VENDOR table
SET SERVEROUTPUT ON
BEGIN
INSERT INTO VENDOR
VALUES (25772,’Clue Store’, ‘Issac
Hayes’, ‘456’, ‘323-2009’, ‘VA’, ‘N’);
DBMS.OUTPUT.PUT_LINE(‘New
Vendor Added’);
END;
/ -- to execute An anonymous PL/SQL Program
PL/SQL block to count the number of
products having different price ranges
DECLARE
W_P1 NUMBER(3) := 0;
W_p2 number(3) := 10;
W_P1 NUMBER(2) := 0;
BEGIN
WHILE W_P2 <300 LOOP
SELECT COUNT(P_CODE) INTO W_NUM FROM PRODUCT
WHERE P_PRICE BETWEEN W_P1 AND W_P2;
DBMS_OUTPUT.PUT_LINE (‘The number of products between’
||W_P1||’and’ || W_P2 || ‘is ’ || W_NUM);
W_P1 := W_P2+1;
W_P2 := W_P2+ 50 ;
END LOOP;
END;
/
STORED PROCEDURES
 A stored procedures is a named collection of procedural
and SQL statements.
 Stored procedures are stored in the database.
 They can be used to encapsulate and represent business
transactions.
 Syntax:
CREATE OR REPLACE PROCEDURE procedure_name
[(argument [IN/OUT] data-type,….. )] [IS/AS]
[variable_name data_type[:=initial_value] ]
BEGIN
PL/SQL or SQL statements
….
Refer to the handouts for
END;
more explanation on
IN/OUT arguments
STORED PROCEDURES
 Advantages:
 Stored procedures substantially reduce traffic as
there is no transmission of individual SQL
statements over the network.
 Stored procedures increase performance because
all the transactions are executed locally on the
RDBMS.
Create a procedure to assign an additional
5percent discount for all products when the
quantity on Hand is more than or equal to twice
the minimum quantity.
CREATE OR REPLACE PROCEDURE
PRC_PROD_DISCOUNT
AS BEGIN
UPDATE PRODUCT
SET P_DISCOUNT = P_DISCOUNT + .05
WHERE P_QOH >= P_MIN*2;
DBMS_OUTPUT.PUT_LINE ('* * Update finished *
*');
END;
STORED PROCEDURES
 To execute the stored procedure, use the
followijg syntax:
 EXEC procedure_name[(paramenter_list)]
Create a procedure to assign an additional percent
discount (an input variable) for all products when the
quantity on Hand is more than or equal to twice the
minimum quantity.
CREATE OR REPLACE PROCEDURE PRC_PROD_DISCOUNT(WPI IN
NUMBER) AS
BEGIN
IF ((WPI <= 0) OR (WPI >= 1)) THEN -- validate WPI parameter
DBMS_OUTPUT.PUT_LINE('Error: Value must be greater than 0 and less
than 1');
ELSE -- if value is greater than 0 and less than 1
UPDATE PRODUCT
SET P_DISCOUNT = P_DISCOUNT + WPI
WHERE P_QOH >= P_MIN*2;
DBMS_OUTPUT.PUT_LINE ('* * Update finished * *');
END IF;
END;
Run the Procedure
EXEC PRC_PROD_DISCOUNT (1.5);
What is the outcome?
EXEC PRC_PROD_DISCOUNT (.05);
What is the outcome?
Oracle Sequences
 MS Access AutoNumber data type fills a column
with unique numeric values
 Oracle sequences
 Independent object in the database
 Named, used anywhere a value expected
 Not tied to a table or column
 Generate numeric values that can be assigned to any
column in any table
 Created and deleted at any time
33
34
Create a procedure which adds a new
invoice.
CREATE OR REPLACE PROCEDURE
PRC_INV_ADD (W_CUS_CODE IN
VARCHAR2, W_DATE IN DATE)
AS BEGIN
INSERT INTO INVOICE
VALUES(INV_NUMBER_SEQ.NEXTVAL,
W_CUS_CODE, W_DATE);
DBMS_OUTPUT.PUT_LINE('Invoice added');
END;
Create a procedure to add a new customer
CREATE OR REPLACE PROCEDURE PRC_CUS_ADD
(W_LN IN VARCHAR, W_FN IN VARCHAR, W_INIT IN VARCHAR,
W_AC IN VARCHAR, W_PH IN VARCHAR)
AS
BEGIN
-- note that the procedure uses the CUS_CODE_SEQ sequence created
earlier. Attribute names are required when not giving values for all
table attributes
INSERT INTO CUSTOMER(CUS_CODE,CUS_LNAME,
CUS_FNAME, CUS_INITIAL, CUS_AREACODE, CUS_PHONE)
VALUES (CUS_CODE_SEQ.NEXTVAL, W_LN, W_FN, W_INIT,
W_AC, W_PH);
DBMS_OUTPUT.PUT_LINE ('Customer ' || W_LN || ', ' || W_FN
|| ' added.');
END;
EXEC PRC_CUS_ADD(‘Walker’, ‘James’,NULL,
‘615’, ‘84-HORSE’);
The result is
Customer Walker, James added.
PL/SQL procedure successfully completed.
Create a procedure which adds a new
product line row for a given invoice.
CREATE OR REPLACE PROCEDURE PRC_LINE_ADD (W_LN IN NUMBER,
W_P_CODE IN VARCHAR2, W_LU NUMBER)
AS
W_LP NUMBER := 0.00;
BEGIN
In order to insert a new record in the
-- GET THE PRODUCT PRICE
LINE table, we need to know the
SELECT P_PRICE INTO W_LP
Invoice Number, Product Code, Line
Units (the values are obtained from the
FROM PRODUCT
input parameters), Line Price ( the value
WHERE P_CODE = W_P_CODE;
is obtained from the Product Price i.e.
p_price) in a PRODUCTTable
-- ADDS THE NEW LINE ROW
INSERT INTO LINE
VALUES(INV_NUMBER_SEQ.CURRVAL, W_LN, W_P_CODE, W_LU,
W_LP,null);
DBMS_OUTPUT.PUT_LINE('Invoice line ' || W_LN || ' added');
END;
Cursor
 A cursor is a special construct in procedural SQL
to hold the data rows returned by an SQL query.
 A cursor is a reserved area of memory in which
the output of the query is stored like an array
holding columns and rows.
 Cursors are held in a reserved memory area in
the DBMS server, not in the client computer.
Cursors
 A cursor is a pointer to a memory location on
database server that the DBMS uses to process a
SQL query
 Cursors are used to retrieve and manipulate
database data in PL/SQL programs
 Types:
 Implicit
 Explicit
Implicit Cursor
Implicit Cursors
 Context area
 A memory location on the database server
 Contains information about query e.g. no. of rows that the
query processes, and a machine language representation of the
query etc.
 Created by INSERT, UPDATE, DELETE, or SELECT
 Active set
 For SELECT queries, the context area also stores the active
set, which is the set of data rows that query retrieves
 Implicit cursor
 is a pointer to the context area
 For Implicit cursor, there is no need to write commands
explicitly to create it or retrieve its value.
Implicit Cursors
 Executing a SELECT query creates an implicit cursor i.e.
Implicit cursor can be used to assign the output of a
SELECT query to PL/SQL program variables when we
are sure that the query will return one and only one
record.
 If the query returns more than one record, or does
not return any record, an error occurs.
Using an Implicit Cursor
 To retrieve data values from a query’s implicit cursor into PL/SQL
program variables add INTO clause :
SELECT field1, field2, ...
INTO variable1, variable2, ...
FROM table1, table2, ...
WHERE join_ conditions
AND
search_condition_to_retrieve_1_record;
 The variables must have been declared in the program’s declaration
section
 The variables must have the same data types as the associated database
fields.
Reference Variables
 Reference variables directly reference specific database field or record and
assume data type of the associated field or record
 %TYPE: is a reference data type which assumes the data type of a database
field
data declaration syntax:
variable_name tablename.fieldname%TYPE;
e.g. current_c_last Customer.Cus_Lname%TYPE;
The current_c_last variable would assume a data type of
VARCHAR2(15), because this is the data type of Cus_Lname field in
the CUSTOMER table
Implicit Cursors (continued)
 Useful to use %TYPE reference data type to declare variables
used with implicit cursors
 variable_name tablename.fieldname%TYPE
 e.g. current_c_last customer.cus_lname%TYPE
Variable name
Table name
Field name in the
table
Reference Variables
 %ROWTYPE: is a reference data type which assumes the data
type of a database record
 data declaration syntax:
row_variable_name tablename%ROWTYPE;
e.g. customer_row Customer%ROWTYPE;
The CUSTOMER_ROW references all of the fields in the
CUSTOMER TABLE, and each field has the same data type as
its associated database fields.
Reference Variables
 How do you refer to individual data field within a
%ROWTYPE variable?
 Use the syntax row_variable_name.fieldname
 If u have to refer to f_first name, you can write
customer_row.cus_fname
or the balance, you can write
customer_row.cus_balance
Reference Data Type used with Cursors
 %TYPE: is a reference data type which assumes the data type of a database
field
 data declaration syntax:
variable_name Cursor_Name.fieldname%TYPE;
e.g. current_c_last
cus_cursor.cus_fname%TYPE;
%ROWTYPE: is a reference data type which assumes the data type of a
database record
 data declaration syntax:
variable_name Cursor_Name%ROWTYPE;
e.g. customer_row cus_cursor%ROWTYPE;
PL/SQL program that displays last name and first name
from the CUSTROMER table where cus_code =10010
using an implicit cursor
SQL> DECLARE
2 current_c_last customer.cus_lname%TYPE;
3 current_c_first customer.cus_fname%TYPE;
4 BEGIN
5
SELECT cus_lname, cus_fname
6
INTO current_C_last, current_C_first
7
FROM customer
8
WHERE cus_code = 10010;
9
DBMS_OUTPUT.PUT_LINE(' The customer ''s
name is ' || current_f_first || ' ' ||
current_f_last);
10
END;
11
/
The customer's name is Ramas Alfred
PL/SQL procedure successfully completed.
Implicit cursor query tried to retrieve multiple records
Error “ORA-01422: exact fetch returns more than requested
number of rows”
SQL> DECLARE
2 current_c_last customer.cus_lname%TYPE;
3 current_c_first customer.cus_fname%TYPE;
4 BEGIN
5
SELECT cus_lname, cus_fname
6
INTO current_f_last, current_f_first
7
FROM customer
8
WHERE cus_lname LIKE ‘S%’;
9
DBMS_OUTPUT.PUT_LINE(' The customer ''s name
is ' || current_f_first || ' ' ||
current_f_last);
10
END;
11
/
DECLARE
*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 8
When implicit cursor query returns no records
SQL> DECLARE
2 current_c_last customer.cus_lname%TYPE;
3 current_c_first customer.cus_fname%TYPE;
4 BEGIN
5
SELECT cus_lname, cus_fname
6
INTO current_f_last, current_f_first
7
FROM customer
8
WHERE cus_code= 12345;
9
DBMS_OUTPUT.PUT_LINE(' The customer ''s
name is ' || current_f_first || ' ' ||
current_f_last);
10
END;
11
/





DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 5
Explicit Cursors
 Explicit cursors are created to retrieve and display data
in PL/SQL programs for query that might
 Retrieve multiple records
 Return no records at all
 Explicit cursors must be explicitly declared in the
program’s declaration section
 Explicit commands are written to process the cursor.
 Steps for creating and using explicit cursor
 Declare cursor
 Open cursor
 Fetch data rows
 Close cursor
Using an Explicit Cursor
Declaring an Explicit Cursor
 By declaring an EC, a memory location is created on the database
server that processes query and stores the records that the query
retrieves
 CURSOR cursor_name IS select_query;
 Cursor_name can be any valid PL/SQL variable name.
 Select_query is the query that retrieves the desired data value (
simple, complex , nested query etc.)
 The query’s search condition can contain PL/SQL variables as
long as the variables are declared before the cursor is declared and
are assigned values before the program opens and processes the
cursor.
Using an Explicit Cursor
 Open the cursor
 OPEN cursor_name;
 When the open command is executed, the PL/SQL
interpreter examines or parses the cursor’s SQL query,
confirms that the query contains no syntax errors and
translates the query into a machine language format.
 The system stores the parsed query in the cursor’s
context area and creates the memory structure that
will store the active set.
 The cursor does not retrieve the data values at this
stage.
Using an Explicit Cursor
 Fetching the data rows
 LOOP
FETCH cursor_name INTO
variable_name(s);
EXIT WHEN cursor_name%NOTFOUND;
It retrieves the query data from the database into the active set, one
row at a time.
The FETCH command associates each field value with a program
variable.
The FETCH command is executed within a loop in order for the
query to return several records.
The cursor variable or variables are declared using either the %TYPE
or %ROWTYPE reference data type.
Using an Explicit Cursor
 Active set pointer
 It is a pointer that indicates the memory location of next record that is
retrieved from database
 When the FETCH command executes past the last record of the query, the
active set pointer points an empty record.
 The exit condition cursor_name%NOTFOUND determines whether
the last cursor record has been fetched by checking if the active pointer is
pointing to the last record and then the loop exits.
 Closing the cursor
 Close the cursor after it processes all of the records in the active set so that
its memory area and resources are available to the system for other tasks.
 CLOSE cursor_name;
 The system automatically closes the cursor when the program that processes
the cursor ends.
Explicit Cursor with %TYPE
 It is used when a cursor retrieves one data field.
Using cursors create a procedure that lists all products
that have a quantity on hand greater than the average
quantity on hand for all products.
CREATE OR REPLACE PROCEDURE PRC_CURSOR_EXAMPLE
IS
W_P_CODE PRODUCT.P_CODE%TYPE;
W_P_DESCRIPT
PRODUCT.P_DESCRIPT%TYPE;
--W_TOT
NUMBER(3);
CURSOR PROD_CURSOR IS
SELECT P_CODE, P_DESCRIPT
FROM PRODUCT
WHERE P_QOH > (SELECT AVG(P_QOH) FROM
PRODUCT);
BEGIN
DBMS_OUTPUT.PUT_LINE('PRODUCTS WITH P_QOH >
AVG(P_QOH)');
DBMS_OUTPUT.PUT_LINE('============================
==========');
OPEN PROD_CURSOR;
LOOP
FETCH PROD_CURSOR INTO W_P_CODE, W_P_DESCRIPT;
EXIT WHEN PROD_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(W_P_CODE ||' -> ' || W_P_DESCRIPT );
END LOOP;
DBMS_OUTPUT.PUT_LINE('============================
==========');
DBMS_OUTPUT.PUT_LINE('TOTAL PRODUCT PROCESSED ' ||
PROD_CURSOR%ROWCOUNT);
DBMS_OUTPUT.PUT_LINE('--- END OF REPORT ----');
CLOSE PROD_CURSOR;
END;
/
Write a program that uses an Explicit Cursor to retrieve and display the invoice
number value (using %TYPE variable) for every record in the INVOICE table for
the customer code 10014.
DECLARE
current_cus_code NUMBER(4);
CURSOR invoice_cursor IS
SELECT inv_number
FROM invoice
WHERE inv_number = current_cus_code;
current_inv invoice.inv_number%TYPE;
BEGIN
OPEN invoice_cursor;
current_inv_num := ‘1001';
DBMS_OUTPUT.PUT_LINE('The current invoice number for
' || current_cus_code || are as follows’);
LOOP
FETCH invoice_cursor INTO current_inv;
EXIT WHEN invoice_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(current_ínv);
END LOOP;
CLOSE invoice_cursor;
END;
/
Explicit Cursor with %ROWTYPE




It is used when a cursor retrieves multiple data fields.
Use a single variable that has %ROWTYPE reference data type
Assume the same data type as the row that the cursor retrieves.
How to declare a cursor %ROWTYPE variable
 row_variable_name cursor_name%ROWTYPE
e.g. customer_row location_cursor%ROWTYPE
 To reference individual data fields within a %ROWTYPE
variable, use
 row_variable_name.fieldname
 e.g. customer_row.room to reference the ROOM
field in the location_row variable.
Write a program that uses an Explicit Cursor to retrieve and display the invoice
number value (using %TYPE variable) for every record in the INVOICE table in
which the customer code is 10014.
DECLARE
current_inv_num NUMBER(4);
CURSOR invoice_cursor IS
SELECT p_code
FROM invoice
WHERE inv_number = current_inv_num;
current_p_code invoice_cursor%ROWTYPE;
BEGIN
OPEN invoice_cursor;
current_inv_num := ‘1001';
LOOP
FETCH invoice_cursor INTO invoice_cursor;
EXIT WHEN invoice_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('The current product code
in ' || current_inv_num || ' ' ||
invoice_p_code.p_code);
END LOOP;
CLOSE invoice_cursor;
END;
/
Triggers
 A Trigger is procedural SQL code that is
automatically invoked by the RDBMS upon the
occurrence of a given data manipulation event.
 A trigger is invoked before or after a data row is
actually inserted, updated or deleted.
 A trigger is associated within a database table.
 Each database table may have one or more triggers.
 A trigger is executed as part of the transaction that
triggered it.
Uses of Triggers
 Triggers can be used to enforce constraints that
cannot be enforced at the DBMS design and
implementation levels.
 Triggers add functionality by automating critical
actions and providing appropriate warnings and
suggestions for remedial action.
 Triggers can be used to update table values, insert
records in tables and call other stored
procedures.
Syntax to create a Trigger in Oracle
CREATE OR REPLACE TRIGGER trigger_name
[BEFORE/AFTER] [DELETE/ INSERT/ UPDATE
OF column_name] ON table_name
[FOR EACH ROW]
[DECLARE]
[varaible_namedata type[:=initial_value] ]
BEGIN
PL/SQL instructions;
………….
END;
Syntax to create a Trigger in Oracle
 The Triggering timing: BEFORE or AFTER. This timing indicates when the
trigger’s PL/SQL code executes; in this case, before or after the triggering
statement is completed. (BEFORE means before the changes are permanently
saved to disk but after the changes are made in memory.)
 The triggering event: the statement that causes the trigger to execute
(INSERT, UPDATE or DELETE).
 The triggering level:
 A statement-level trigger is assumed if we omit the FOR EACH ROW keywords. This
executes only once before or after the triggering statement is completed.
 A row-level trigger requires use of the FOR EACH ROW keywords. This is executed
once for reach row affected by the triggering statement.
 The Triggering action: The PL/SQL code enclosed between the BEGIN and
END keywords. Each statement inside the PL/SQL code must end with a
semicolon.
Example
 Create a trigger which should be activated when a product’s
quantity on hand is updated when the product is sold, the
system should automatically check whether the quantity on
hand falls below its minimum allowable quantity.
CREATE OR REPLACE TRIGGER TRG_PRODUCT_REORDER
AFTER INSERT OR UPDATE OF P_QOH ON PRODUCT
BEGIN
UPDATE PRODUCT
SET P_REORDER = 1
WHER P_QOH <= P_MIN;
END;
/
Verifying The Trigger
SELECT * FROM PRODUCT WHERE P_CODE
=‘11QER/31’;
-------UPDATE PRODUCT
SET P_QOH = 4
WHERE P_CODE =‘ 11QER/31’;
--------
SELECT * FROM PRODUCT WHERE P_CODE
=‘11QER/31’;
SECOND version of the
TRG_PRODUCT_REORDER TRIGGER
 What happens if we reduce the minimum quantity of product
‘2232/QWE’?
 When we update the P_MIN column, the trigger is never executed.
TRG_PRODUCT_REORDER executes only after an update of the P_QOH
column.
 To avoid that inconsistency we need to modify the trigger event.
CREATE OR REPLACE TRIGGER TRG_PRODUCT_REORDER
AFTER INSERT OR UPDATE OF P_QOH, P_MIN ON PRODUCT
BEGIN
UPDATE PRODUCT
SET P_REORDER = 1
WHER P_QOH <= P_MIN;
END;
/
What happens if we change the P_QOH
value for product ‘11QER/31 from 4 to
29 when the P_MIN is set to 5 and
P_REORDER is 1’
 The P_REORDER flag is still set to 1 because the
trigger sets the P_REORDER value only to1;it does not
reset the value to 0, even if such an action is clearly
required when the inventory level is back to a value
greater than the minimum value.
 Why did not the trigger change the reorder flag to 0?
Third version of the
TRG_PRODUCT_REORDER TRIGGER
 To avoid that inconsistency we need to modify the trigger
event.
CREATE OR REPLACE TRIGGER TRG_PRODUCT_REORDER
BEFORE INSERT OR UPDATE OF P_QOH, P_MIN ON PRODUCT
FOR EACH ROW
BEGIN
IF :NEW.P_QOH <=:NEW.P_MIN THEN
:NEW.P_REORDER :=1;
ELSE
:NEW.P_REORDER :=0;
ENDIF;
END;
/
Third version of the
TRG_PRODUCT_REORDER TRIGGER
 The computer cannot change anything directly in
permanent storage (disk).It must read the data
from permanent storage to primary memory;
then it makes the change in primary memory and
finally, it writes the changed data back to
permanent memory (disk).
 All changes are done first in primary memory,
then are transferred to permanent memory.
Third version of the
TRG_PRODUCT_REORDER TRIGGER
 To ensure data integrity, DBMS makes two copies
of every row being changed by a DML statement.
The first copy contains the original(old) value of
the attributes before the changes. The second
copy contains the changed(new) values of the
attributes that will be permanently saved to the
database.

Create a Trigger to update an attribute in
a table other than the one being modified
Example: Create a trigger that automatically
reduces the quantity on hand of a product
with every sale.
CREATE OR REPLACE TRIGGER TRG_LINE_PROD
AFTER INSERT ON LINE
FOR EACH ROW
BEGIN
UPDATE PRODUCT
SET P_QOH =P_QOH :NEW.LINE_UNITS
WHERE PRODUCT.P_CODE = :NEW.P_CODE;
END;
/
Use of variables within a trigger
Example:
Create a trigger to update the customer
balance(CUS_BALANCE) in the CUSTOMER table
after inserting every new LINE row. The trigger code
is
CREATE OR REPLACE TRIGGER TRG_LINE_CUS
AFTER INSERT ON LINE
FOR EACH ROW
DECLARE
W_CUS
CHAR(5);
W_TOT
NUMBER:= 0; -- to compute total cost
BEGIN
-- this trigger fires up after an INSERT of a LINE
-- it will update the CUS_BALANCE in CUSTOMER
Use of variables within a trigger
-- 1) get the CUS_CODE
SELECT CUS_CODE INTO W_CUS
FROM INVOICE
WHERE INVOICE.INV_NUMBER = :NEW.INV_NUMBER;
-- 2) compute the total of the current line
W_TOT := :NEW.LINE_PRICE * :NEW.LINE_UNITS;
-- 3) Update the CUS_BALANCE in CUSTOMER
UPDATE CUSTOMER
SET CUS_BALANCE = CUS_BALANCE + W_TOT
WHERE CUS_CODE = W_CUS;
END;
Deleting a Trigger
 Although triggers are independent objects, they
are associated with database tables. When you
delete a table, all its trigger objects are deleted
with it.
 To delete a trigger
 DROP TRIGGER trigger_name;
Trigger Action Based On
Conditional DML Predicates
 Triggers are created depending on the type of DML
statements such as INSERT or UPDATE or DELETE that
fires the trigger.
 But how would we know which one of the three
statements caused the trigger to execute? In those cases,
we could use the following syntax:
IF UPDATTING THEN ….ENDIF;
IF INSERTING THEN… ENDIF;
IF DELETING THEN … ENDIF;
PL/SQL Stored Functions
 We can create our own stored functions.
 Stored procedures and functions are very similar.
 A stored function is basically a named group of
procedural and SQL statements that returns a
value indicated by a RETURN in its program
code.
 We can use function in the right side of the
assignment statement.
PL/SQL Stored Functions
 Syntax:
CREATE FUNCTION function_name(argument IN
data-type,….) RETURN data-type [IS]
BEGIN
PL/SQL statements;
……
RETURN (value or expression);
END;
Descargar

PL/SQL