PLSQL
PLSQL
About PL/SQL
• PL/SQL:
– Stands for “Procedural Language extension to SQL”
– Is Oracle Corporation’s standard data access language
for relational databases
– Seamlessly integrates procedural constructs with SQL
About PL/SQL
• PL/SQL:
– Provides a block structure for executable units of code.
Maintenance of code is made easier with such a well-
defined structure.
– Provides procedural constructs such as:
• Variables, constants, and data types
• Control structures such as conditional statements and loops
• Reusable program units that are written once and executed
many times
PL/SQL Environment
PL/SQL engine
procedural Procedural
PL/SQL statement
PLSQL
block executor
SQL
SQL statement
executor
SQL 1
SQL 2
…
SQL
IF...THEN
SQL
ELSE
SQL
END IF;
SQL
Benefits of PL/SQL
– Modularized program development
– Integration with Oracle tools
– Portability
– Exception handling
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)
Block Types
Anonymous Procedure Function
DECLARE
V_fname VARCHAR2(20);
BEGIN
SELECT first_name
INTO v_fname
FROM employees
WHERE employee_id=100;
END;
Test the Output of a PL/SQL Block
– Enable output in SQL Developer by clicking the
Enable DBMS Output button on the DBMS Output
tab:
SELECT
first_name,
department_id
INTO Jennifer v_fname
v_fname,
v_deptno
FROM …
10 v_deptno
Requirements for Variable Names
• A variable name:
– Must start with a letter
– Can include letters or numbers
– Can include special characters (such as $, _, and # )
– Must contain no more than 30 characters
– Must not include reserved words
Handling Variables in PL/SQL
• Variables are:
– Declared and initialized in the declarative section
– Used and assigned new values in the executable
section
– Passed as parameters to PL/SQL subprograms
– Used to hold the output of a PL/SQL subprogram
Declaring and Initializing PL/SQL
Variables
• Syntax:
identifier [CONSTANT] datatype [NOT NULL]
[:= | DEFAULT expr];
• Examples:
DECLARE
v_hiredate DATE;
v_deptno NUMBER(2) NOT NULL := 10;
v_location VARCHAR2(13) := 'Atlanta';
c_comm CONSTANT NUMBER := 1400;
Declaring and Initializing PL/SQL
Variables
DECLARE
v_myName VARCHAR2(20);
BEGIN
DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
v_myName := 'John';
1 DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
END;
/
OUTPUT
My name is:
My name is: John
PL/SQL procedure successfully completed.
DECLARE
v_myName VARCHAR2(20):= 'John';
BEGIN
v_myName := 'Steven';
2 DBMS_OUTPUT.PUT_LINE('My name is: '|| v_myName);
END;
/
OUTPUT
My name is: Steven
PL/SQL procedure successfully completed.
Types of Variables
– PL/SQL variables:
• Scalar
• Composite
• Reference
• Large object (LOB)
– Non-PL/SQL variables: Bind variables
Types of Variables
TRUE 25-JAN-13
3.14285714
INDIA
Guidelines for Declaring and Initializing
PL/SQL Variables
– Follow naming conventions.
– Use meaningful identifiers for variables.
– Initialize variables designated as NOT NULL and
CONSTANT.
– Initialize variables with the assignment operator (:=) or
the DEFAULT keyword:
v_myName VARCHAR2(20):='John';
TRUE 25-JAN-13
3.14285714 INDIA
Base Scalar Data Types
– CHAR [(maximum_length)]
– VARCHAR2 (maximum_length)
– NUMBER [(precision, scale)]
– BINARY_INTEGER
– PLS_INTEGER
– BOOLEAN
– BINARY_FLOAT
– BINARY_DOUBLE
Base Scalar Data Types
– DATE
– TIMESTAMP
– TIMESTAMP WITH TIME ZONE
– TIMESTAMP WITH LOCAL TIME ZONE
– INTERVAL YEAR TO MONTH
– INTERVAL DAY TO SECOND
Declaring Scalar Variables
• Examples:
DECLARE
v_emp_job VARCHAR2(9);
v_count_loop BINARY_INTEGER := 0;
v_dept_total_sal NUMBER(9,2) := 0;
v_orderdate DATE := SYSDATE + 7;
c_tax_rate CONSTANT NUMBER(3,2) := 8.25;
v_valid BOOLEAN NOT NULL := TRUE;
...
%TYPE Attribute
– Is used to declare a variable according to:
• A database column definition
• Another declared variable
– Is prefixed with:
• The database table and column
• The name of the declared variable
Declaring Variables
with the %TYPE Attribute
• Syntax
identifier table.column_name%TYPE;
• Examples
...
emp_lname employees.last_name%TYPE;
...
...
balance NUMBER(7,2);
min_balance balance%TYPE := 1000;
...
Declaring Boolean Variables
– Only the TRUE, FALSE, and NULL values can be assigned to
a Boolean variable.
– Conditional expressions use the logical operators AND and OR
and the unary operator NOT to check the variable values.
– The variables always yield TRUE, FALSE, or NULL.
– Arithmetic, character, and date expressions can be used to
return a Boolean value.
Bind Variables
• Bind variables are:
– Created in the environment
– Also called host variables
– Created with the VARIABLE keyword
– Used in SQL statements and PL/SQL blocks
– Accessed even after the PL/SQL block is executed
– Referenced with a preceding colon
Printing Bind Variables
• Example:
Photo
(BLOB)
Movie
(BFILE)
NCLOB
Composite Data Types
1 SMITH 1 5000
2 JONES 2 2345
3 NANCY 3 12
4 TIM 4 3456
VARCHAR2 NUMBER
PLS_INTEGER PLS_INTEGER
THANKS
Writing Executable Statements
Topics To Cover
– Identify lexical units in a PL/SQL block
– Use built-in SQL functions in PL/SQL
– Describe when implicit conversions take place and
when explicit conversions have to be dealt with
– Write nested blocks and qualify variables with
labels
– Write readable code with appropriate indentation
– Use sequences in PL/SQL expressions
Lexical Units in a PL/SQL Block
• Lexical units:
– Are building blocks of any PL/SQL block
– Are sequences of characters including letters,
numerals, tabs, spaces, returns, and symbols
– Can be classified as:
• Identifiers: v_fname, c_percent
• Delimiters: ; , +, -
• Literals: John, 428, True
• Comments: --, /* */
PL/SQL Block Syntax and Guidelines
– Literals
• Character and date literals must be enclosed in single
quotation marks.
• Numbers can be simple values or in scientific notation.
name := 'Henderson';
DECLARE
v_outer_variable VARCHAR2(20):='GLOBAL VARIABLE';
BEGIN
DECLARE
v_inner_variable VARCHAR2(20):='LOCAL VARIABLE';
BEGIN
DBMS_OUTPUT.PUT_LINE(v_inner_variable);
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
END;
DBMS_OUTPUT.PUT_LINE(v_outer_variable);
END;
Variable Scope and Visibility
OUTPUT:
DECLARE
Father's Name: Patrick
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972'; Date of Birth: 12-DEC-02
BEGIN Child's Name: Mike
DECLARE Date of Birth: 20-APR-72
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
1 DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
DBMS_OUTPUT.PUT_LINE('Child''s Name: '||v_child_name);
2 END;
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
END;
/
Qualify an Identifier
BEGIN <<outer>>
DECLARE
v_father_name VARCHAR2(20):='Patrick';
v_date_of_birth DATE:='20-Apr-1972';
BEGIN
DECLARE
v_child_name VARCHAR2(20):='Mike';
v_date_of_birth DATE:='12-Dec-2002';
BEGIN
DBMS_OUTPUT.PUT_LINE('Father''s Name: '||v_father_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '
||outer.v_date_of_birth);
DBMS_OUTPUT.PUT_LINE('Child''s Name: '||v_child_name);
DBMS_OUTPUT.PUT_LINE('Date of Birth: '||v_date_of_birth);
END;
END;
END outer;
Operators in PL/SQL
– Logical
– Arithmetic
– Concatenation
– Parentheses to control order
of operations
} Same as in SQL
SELECT select_list
INTO {variable_name[, variable_name]...
| record_name}
FROM table
[WHERE condition];
SELECT Statements in PL/SQL
– The INTO clause is required.
– Queries must return only one row.
• Example:
DECLARE
v_fname VARCHAR2(25);
BEGIN
SELECT first_name INTO v_fname
FROM employees WHERE employee_id=200;
DBMS_OUTPUT.PUT_LINE(' First Name is : '||v_fname);
END;
/
Retrieving Data in PL/SQL
• Retrieve hire_date and salary for the specified employee.
• Example:
DECLARE
v_emp_hiredate employees.hire_date%TYPE;
v_emp_salary employees.salary%TYPE;
BEGIN
SELECT hire_date, salary
INTO v_emp_hiredate, v_emp_salary
FROM employees
WHERE employee_id = 100;
END;
/
Retrieving Data in PL/SQL
• Return the sum of the salaries for all the employees in
the specified department.
• Example:
DECLARE
v_sum_sal NUMBER(10,2);
v_deptno NUMBER NOT NULL := 60;
BEGIN
SELECT SUM(salary) -- group function
INTO v_sum_sal FROM employees
WHERE department_id = v_deptno;
DBMS_OUTPUT.PUT_LINE ('The sum of salary is ' || v_sum_sal);
END;
Naming Conventions
• DECLARE
• hire_date employees.hire_date%TYPE;
• sysdate hire_date%TYPE;
• employee_id employees.employee_id%TYPE := 176;
• BEGIN
• SELECT hire_date, sysdate
• INTO hire_date, sysdate
• FROM employees
• WHERE employee_id = employee_id;
• END;
• /
Naming Conventions
– Use a naming convention to avoid ambiguity in the
WHERE clause.
– Avoid using database column names as identifiers.
– Syntax errors can arise because PL/SQL checks the
database first for a column in the table.
– The names of local variables and formal parameters
take precedence over the names of database tables.
– The names of database table columns take
precedence over the names of local variables.
Using PL/SQL to Manipulate Data
• Make changes to database tables by using DML commands:
– INSERT
– UPDATE
– DELETE
– MERGE DELETE
INSERT
MERGE
UPDATE
Inserting Data
• Add new employee information to the EMPLOYEES table.
• Example:
BEGIN
INSERT INTO employees
(employee_id, first_name, last_name, email,
hire_date, job_id, salary)
VALUES(employees_seq.NEXTVAL, 'Ruth', 'Cores',
'RCORES',CURRENT_DATE, 'AD_ASST', 4000);
END;
/
Updating Data
• Increase the salary of all employees who are stock clerks.
• Example:
DECLARE
sal_increase employees.salary%TYPE := 800;
BEGIN
UPDATE employees
SET salary = salary + sal_increase
WHERE job_id = 'ST_CLERK';
END;
/
Deleting Data
• Delete rows that belong to department 10 from the
employees table.
• Example:
DECLARE
deptno employees.department_id%TYPE := 10;
BEGIN
DELETE FROM employees
WHERE department_id = deptno;
END;
/
Merging Rows
• Insert or update rows in the copy_emp table to match the
employees table.
BEGIN
MERGE INTO copy_emp c
USING employees e
ON (e.employee_id = c.empno)
WHEN MATCHED THEN
UPDATE SET
c.first_name = e.first_name,
c.last_name = e.last_name,
c.email = e.email,
. . .
WHEN NOT MATCHED THEN
INSERT VALUES(e.employee_id, e.first_name, e.last_name,
. . .,e.department_id);
END;
/
SQL Cursor
– A cursor is a pointer to the private memory area
allocated by the Oracle server.
– A cursor is used to handle the result set of a
SELECT statement.
– There are two types of cursors:
• Implicit: Created and managed internally by the Oracle
server to process SQL statements
• Explicit: Declared explicitly by the programmer
SQL Cursor Attributes for Implicit
Cursors
• Using SQL cursor attributes, you can test the outcome of your
SQL statements.
DECLARE
v_rows_deleted VARCHAR2(30)
v_empno employees.employee_id%TYPE := 176;
BEGIN
DELETE FROM employees
WHERE employee_id = v_empno;
v_rows_deleted := (SQL%ROWCOUNT ||
' row deleted.');
DBMS_OUTPUT.PUT_LINE (v_rows_deleted);
END;
THANKS
Writing Control Structures
Topics To Cover
– Identify the uses and types of control structures
– Construct an IF statement
– Use CASE statements and CASE expressions
– Construct and identify loop statements
– Use guidelines when using conditional control
structures
Controlling Flow of Execution
for
. .
loop
. .
.
while
IF Statement
• Syntax:
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
Simple IF Statement
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
END IF;
END;
/
• Output:
IF THEN ELSE Statement
DECLARE
v_myage number:=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
/
• Output:
DECLARE
IF ELSIF ELSE Clause
v_myage number:=31;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSIF v_myage < 20 THEN
DBMS_OUTPUT.PUT_LINE(' I am young ');
ELSIF v_myage < 30 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my twenties');
ELSIF v_myage < 40 THEN
DBMS_OUTPUT.PUT_LINE(' I am in my thirties');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am always young ');
END IF;
END;
/
Output:
NULL Value in IF Statement
DECLARE
v_myage number;
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am not a child ');
END IF;
END;
/
CASE Expressions
– A CASE expression selects a result and returns it.
– To select the result, the CASE expression uses
expressions. The value returned by these expressions is
used to select one of several alternatives.
CASE selector
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
[ELSE resultN+1]
END;
/
CASE Expressions: Example
SET VERIFY OFF
DECLARE
v_grade CHAR(1) := UPPER('&grade');
appraisal VARCHAR2(20);
BEGIN
appraisal := CASE v_grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| v_grade || '
Appraisal ' || appraisal);
END;
/
Searched CASE Expressions
DECLARE
v_grade CHAR(1) := UPPER('&grade');
appraisal VARCHAR2(20);
BEGIN
appraisal := CASE
WHEN v_grade = 'A' THEN 'Excellent'
WHEN v_grade IN ('B','C') THEN 'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| v_grade || '
Appraisal ' || appraisal);
END;
/
CASE Statement
DECLARE
v_deptid NUMBER;
v_deptname VARCHAR2(20);
v_emps NUMBER;
v_mngid NUMBER:= 108;
BEGIN
CASE v_mngid
WHEN 108 THEN
SELECT department_id, department_name
INTO v_deptid, v_deptname FROM departments
WHERE manager_id=108;
SELECT count(*) INTO v_emps FROM employees
WHERE department_id=v_deptid;
WHEN 200 THEN
...
END CASE;
DBMS_OUTPUT.PUT_LINE ('You are working in the '|| deptname||
' department. There are '||v_emps ||' employees in this
department');
END;
/
Handling Nulls
• When working with nulls, you can avoid some
common mistakes by keeping in mind the following
rules:
– Simple comparisons involving nulls always yield NULL.
– Applying the logical operator NOT to a null yields NULL.
– If the condition yields NULL in conditional control
statements, its associated sequence of statements is not
executed.
Logic Tables
• Build a simple Boolean condition with a
comparison
AND operator.
TRUE FALSE NULL OR TRUE FALSE NULL NOT
TRUE TRUE FALSE NULL TRUE TRUE TRUE TRUE TRUE FALSE
FALSE FALSE FALSE FALSE FALSE TRUE FALSE NULL FALSE TRUE
NULL NULL FALSE NULL NULL TRUE NULL NULL NULL NULL
Boolean Conditions
• What is the value of flag in each case?
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_counter NUMBER(2) := 1;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + v_counter), v_new_city, v_countryid);
v_counter := v_counter + 1;
EXIT WHEN v_counter > 3;
END LOOP;
END;
/
WHILE Loops
• Syntax:
WHILE condition LOOP
statement1;
statement2;
. . .
END LOOP;
• Use the WHILE loop to repeat statements while a
condition is TRUE.
WHILE Loops
• Example
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
v_counter NUMBER := 1;
BEGIN
SELECT MAX(location_id) INTO v_loc_id FROM locations
WHERE country_id = v_countryid;
WHILE v_counter <= 3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + v_counter), v_new_city, v_countryid);
v_counter := v_counter + 1;
END LOOP;
END;
/
FOR Loops
– Use a FOR loop to shortcut the test for the number of
iterations.
– Do not declare the counter; it is declared implicitly.
DECLARE
v_countryid locations.country_id%TYPE := 'CA';
v_loc_id locations.location_id%TYPE;
v_new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO v_loc_id
FROM locations
WHERE country_id = v_countryid;
FOR i IN 1..3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((v_loc_id + i), v_new_city, v_countryid );
END LOOP;
END;
/
FOR Loops
• Guidelines
– Reference the counter within the loop only; it is undefined
outside the loop.
– Do not reference the counter as the target of an assignment.
– Neither loop bound should be NULL.
Guidelines for Loops
– Use the basic loop when the statements inside the loop
must execute at least once.
– Use the WHILE loop if the condition must be evaluated
at the start of each iteration.
– Use a FOR loop if the number of iterations is known.
Nested Loops and Labels
– You can nest loops to multiple levels.
– Use labels to distinguish between blocks and
loops.
– Exit the outer loop with the EXIT statement
that references the label.
Nested Loops and Labels
...
BEGIN
<<Outer_loop>>
LOOP
v_counter := v_counter+1;
EXIT WHEN v_counter>10;
<<Inner_loop>>
LOOP
...
EXIT Outer_loop WHEN total_done = 'YES';
-- Leave both loops
EXIT WHEN inner_done = 'YES';
-- Leave inner loop only
...
END LOOP Inner_loop;
...
END LOOP Outer_loop;
END;
/
PL/SQL CONTINUE Statement
– Definition
• Adds the functionality to begin the next loop
iteration
• Provides programmers with the ability to transfer
control to the next iteration of a loop
• Uses parallel structure and semantics to the EXIT
statement
– Benefits
• Eases the programming process
• May see a small performance improvement over the
previous programming workarounds to simulate the
CONTINUE statement
PL/SQL CONTINUE Statement:
Example
anonymous block completed
DECLARE
Total is: 1
v_total SIMPLE_INTEGER := 0;
Out of Loop Total is: 2
BEGIN
Total is: 4
FOR i IN 1..10 LOOP
Out of Loop Total is: 6
1 v_total := v_total + i; Total is: 9
dbms_output.put_line
Out of Loop Total is: 12
('Total is: '|| v_total);
Total is: 16
CONTINUE WHEN i > 5;
Out of Loop Total is: 20
v_total := v_total + i;
Total is: 25
2 dbms_output.put_line Out of Loop Total is: 30
('Out of Loop Total is:
Total is: 36
'|| v_total);
Total is: 43
END LOOP;
Total is: 51
END;
Total is: 60
/
Total is: 70
THANKS
Working with
Composite Data Types
Topics To Cover
– Create user-defined PL/SQL records
– Create a record with the %ROWTYPE attribute
– Create an INDEX BY table
– Create an INDEX BY table of records
– Varray,Nested table
– Describe the differences between Index by
Table,Varray,Nested Table.
Composite Data Types
– Can hold multiple values (unlike scalar types)
– Are of two types:
• PL/SQL records
• PL/SQL collections
– INDEX BY tables or associative arrays
– Nested table
– VARRAY
Composite Data Types
– Use PL/SQL records when you want to store values of
different data types but only one occurrence at a time.
– Use PL/SQL collections when you want to store values of
the same data type.
PL/SQL Records
– Must contain one or more components (called fields) of
any scalar, RECORD, or INDEX BY table data type
– Are similar to structures in most third-generation
languages (including C and C++)
– Are user defined and can be a subset of a row in a table
– Treat a collection of fields as a logical unit
– Are convenient for fetching a row of data from a table
for processing
Creating a PL/SQL Record
• Syntax:
1 TYPE type_name IS RECORD
(field_declaration[, field_declaration]…);
2 identifier type_name;
field_declaration:
field_name {field_type | variable%TYPE
| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]
Creating a PL/SQL Record
• Declare variables to store the name, job, and salary of a
new employee.
• Example:
DECLARE
type t_rec is record
(v_sal number(8),
v_minsal number(8) default 1000,
v_hire_date employees.hire_date%type,
v_rec1 employees%rowtype);
v_myrec t_rec;
BEGIN
v_myrec.v_sal := v_myrec.v_minsal + 500;
v_myrec.v_hire_date := sysdate;
SELECT * INTO v_myrec.v_rec1
FROM employees WHERE employee_id = 100;
DBMS_OUTPUT.PUT_LINE(v_myrec.v_rec1.last_name ||' '||
to_char(v_myrec.v_hire_date) ||' '|| to_char(v_myrec.v_sal));
END;
PL/SQL Record Structure
Example:
DECLARE
identifier reference%ROWTYPE;
Advantages of Using %ROWTYPE
– The number and data types of the underlying
database columns need not be known—and, in fact,
might change at run time.
– The %ROWTYPE attribute is useful when retrieving
a row with the SELECT * statement.
%ROWTYPE Attribute: Example
DECLARE
v_employee_number number:= 124;
v_emp_rec employees%ROWTYPE;
BEGIN
SELECT * INTO v_emp_rec FROM employees
WHERE employee_id = v_employee_number;
INSERT INTO retired_emps(empno, ename, job, mgr,
hiredate, leavedate, sal, comm, deptno)
VALUES (v_emp_rec.employee_id, v_emp_rec.last_name,
v_emp_rec.job_id, v_emp_rec.manager_id,
v_emp_rec.hire_date, SYSDATE,
v_emp_rec.salary, v_emp_rec.commission_pct,
v_emp_rec.department_id);
END;
/
Inserting a Record
by Using %ROWTYPE
...
DECLARE
v_employee_number number:= 124;
v_emp_rec retired_emps%ROWTYPE;
BEGIN
SELECT employee_id, last_name, job_id, manager_id,
hire_date, hire_date, salary, commission_pct,
department_id INTO v_emp_rec FROM employees
WHERE employee_id = v_employee_number;
INSERT INTO retired_emps VALUES v_emp_rec;
END;
/
SELECT * FROM retired_emps;
Updating a Row in a Table
by Using a Record
SET VERIFY OFF
DECLARE
v_employee_number number:= 124;
v_emp_rec retired_emps%ROWTYPE;
BEGIN
SELECT * INTO v_emp_rec FROM retired_emps;
v_emp_rec.leavedate:=CURRENT_DATE;
UPDATE retired_emps SET ROW = v_emp_rec WHERE
empno=v_employee_number;
END;
/
SELECT * FROM retired_emps;
INDEX BY Tables or Associative
Arrays
– Are PL/SQL structures with two columns:
• Primary key of integer or string data type
• Column of scalar or record data type
– Are unconstrained in size. However, the size
depends on the values that the key data type can
hold.
– Local index tables in the form of an array
– Arbitrary numbers or strings can be used as
subscript values
– These can not be stored inside the database
Creating an INDEX BY Table
• Syntax:
TYPE type_name IS TABLE OF
{column_type | variable%TYPE
| table.column%TYPE} [NOT NULL]
| table%ROWTYPE
[INDEX BY PLS_INTEGER | BINARY_INTEGER
| VARCHAR2(<size>)];
identifier type_name;
...
TYPE ename_table_type IS TABLE OF
• Declare an INDEX BY table to store the
employees.last_name%TYPE
INDEX BY PLS_INTEGER;
last names of employees:
...
ename_table ename_table_type;
INDEX BY Table Structure
1 Jones
5 Smith
3 Maduro
... ...
PLS_INTEGER Scalar
Declaring Index by Table in an Anonymous
block: Example
DECLARE
-- Declaring a simple Index by table of number
TYPE my_plsql_tab IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER ;
-- Creating a variable of PLSQL Table (my_tab) type
t_type my_plsql_tab ;
BEGIN
FOR i IN 1 .. 10
LOOP
-- Initializing Array
t_type(i) := i ;
END LOOP ;
FOR i IN 1 .. 10
LOOP
-- Accessing array elements
DBMS_OUTPUT.PUT_LINE(t_type(i)) ;
END LOOP ;
END ;
Creating an INDEX BY Table
• DECLARE
• TYPE ename_table_type IS TABLE OF
• employees.last_name%TYPE
• INDEX BY PLS_INTEGER;
• TYPE hiredate_table_type IS TABLE OF DATE
• INDEX BY PLS_INTEGER;
• ename_table ename_table_type;
• hiredate_table hiredate_table_type;
• BEGIN
• ename_table(1) := 'CAMERON';
• hiredate_table(8) := SYSDATE + 7;
• IF ename_table.EXISTS(1) THEN
• INSERT INTO ...
• ...
• END;
• /
INDEX BY Table of Records
• Define an INDEX BY table variable to hold
an entire row from a table.
•DECLARE
Example:
TYPE dept_table_typeIS TABLE OF
departments%ROWTYPE
INDEX BY VARCHAR2(20);
dept_table dept_table_type;
-- Each element of dept_table is a record
INDEX BY Table of Records:
Example
DECLARE
TYPE emp_table_type IS TABLE OF
employees%ROWTYPE INDEX BY PLS_INTEGER;
my_emp_table emp_table_type;
max_count NUMBER(3):= 104;
BEGIN
FOR i IN 100..max_count
LOOP
SELECT * INTO my_emp_table(i) FROM employees
WHERE employee_id = i;
END LOOP;
FOR i IN my_emp_table.FIRST..my_emp_table.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(my_emp_table(i).last_name);
END LOOP;
END;
/
Nested Tables
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
Collection type – Nested Tables
• Nested tables
– Hold an arbitrary number of elements
– They use sequential numbers as subscripts
– Can be stored in database tables
– Can be manipulated through SQL
• SYNTAX
TYPE type_name IS TABLE OF element_type
[NOT NULL];
Declaring Nested Table in an Anonymous
block: Example
DECLARE
-- Declaring a nested table collection type
t_nt_var nested_table_type ;
BEGIN
-- Initializing Array
t_nt_var := nested_table_type( 'Shipping', 'Sales',
'Finance' , 'Payroll' );
-- Accessing array elements
FOR j IN 1 .. 4
LOOP
DBMS_OUTPUT.PUT_LINE(t_nt_var(j));
END LOOP;
END;
VARRAY
A variable-size array (VARRAY) is similar to a PL/SQL
table, except that a VARRAY is constrained in size.
1 Bombay
2 Sydney
3 Oxford
4 London
.. ....
10 Tokyo
Collection Type - Varrays
• Varrays (variable-size arrays)
• Uses sequential numbers as subscripts
• Cannot remove/delete individual elements from the array
• Length defined at design time can be manipulated at runtime;
However not beyond the max size specified in declaration
• Can be stored and retrieved through SQL
• Less flexible than nested tables
• Syntax:
TYPE type_name IS VARRAY(max_size) OF element data_type;
• Max_size is the maximum no of elements to be allowed for the
array
• Element_data_type is the Data Type of the elements
• Varrays can be used:
– In an Anonymous block
– In database along with various DML commands and method usage
Varrays in an Anonymous Block:
Example
DECLARE
TYPE t_names IS VARRAY(5) OF VARCHAR2(20);
v_name_list t_names :=
t_names('Amit','Summet','Rajesh','Milind','Sachin'
);
BEGIN
FOR cnt IN 1 .. v_name_list.count
LOOP
DBMS_OUTPUT.PUT_LINE('Name :'||
v_name_list(cnt));
END LOOP;
END;
Methods In Collection
• Various methods available for collections are:
– Exists(n): Returns TRUE if nth element exists in Varray
– Count: Returns the number of elements in the Varray
– Limit: Gives the Maximum size of the array
– First & Last: Returns the First and Last index number in
the collection
– Extend(n): Increases the size of collection by n. Appends
n elements to a collection
– Delete(n): Removes an element form nth index
– Trim(n): Removes last n elements from the Collection
DIFFERENCES BETWEEN COLLECTIONS
Thanks
THANKS
Handling Exceptions
Topics To Cover
– Define PL/SQL exceptions
– Recognize unhandled exceptions
– List and use different types of PL/SQL exception
handlers
– Trap unanticipated errors
– Describe the effect of exception propagation in
nested blocks
– Customize PL/SQL exception messages
Example of an Exception
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees
WHERE first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is :'
||v_lname);
END;
Example of an Exception
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees
WHERE first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is :'
||v_lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (' Your select statement
retrieved multiple rows. Consider using a
cursor.');
END;
/
Handling Exceptions with PL/SQL
– An exception is a PL/SQL error that is raised during
program execution.
– An exception can be raised:
• Implicitly by the Oracle server
• Explicitly by the program
– An exception can be handled:
• By trapping it with a handler
• By propagating it to the calling environment
Handling Exceptions
DECLAR
……. Is the
BEGIN
exception Terminate
……. No abruptly.
…….
trapped?
Yes
Terminate
gracefully.
Exception Types
– Predefined Oracle server
– Non-predefined Oracle server
} Implicitly raised
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
• Exception section:
RAISE_APPLICATION_ERROR (-20201,
'Manager is not a valid employee.');
END;
/
THANKS
Creating Stored Procedures and
Functions
Topics To Cover
– Differentiate between anonymous blocks and
subprograms
– Create a simple procedure and invoke it from an
anonymous block
– Create a simple function
– Create a simple function that accepts a parameter
– Differentiate between procedures and functions
Procedures and Functions
– Are named PL/SQL blocks
– Are called PL/SQL subprograms
– Have block structures similar to anonymous blocks:
• Optional declarative section (without the DECLARE keyword)
• Mandatory executable section
• Optional section to handle exceptions
Differences Between Anonymous
Blocks and Subprograms
Anonymous Blocks Subprograms
Unnamed PL/SQL blocks Named PL/SQL blocks
13-165
Topics To cover
• Package – Concept
• Package – Specification
• Package – Body
Package – Concept
• Package is schema object that groups logically
related plsql types, item and subprograms.
– Package specification
– Package body
– All Procedure and Function inside body can use the variable,
types , exception and cursors declared in specification.
Package Body
• Syntax: Creating package Body
END EMPPack;
Package Body
• Emppack body has:
– One private variable v_sal that can be used only inside this
package.
PackageName.Proc_Name(parameters);
EmpPack.CalculateBonus(10);
– On SQL prompt :
Execute PackageName.Proc_Name(parameters);
Execute EmpPack.CalculateBonus(10);
Use Package
• To call function in a package
Variable := PackageName.Func_Name(parameters);
– On SQL prompt :
Select PackageName.Func_Name(parameters) from dual;
• Execute EmpPack.UpdateDept(7689,20);
• Try out :
– Describe USER_OBJECTS;
– select object_type, object_name from
user_objects where object_type = ‘PACKAGE' ;
USER_CODE
• This is the view Oracle provides you to see the code of all package you have
created.
17-192
Topics To Cover
6
– Describe the different types of triggers
5
4
3
2 – Create database triggers
1
– Describe database trigger-firing rules
17-193
What Are Triggers?
A trigger is a PL/SQL block that is stored in the database
and fired (executed) in response to a specified event.
17-194
Defining Triggers
17-195
Trigger Event Types
You can write triggers that fire whenever one of the
following operations occurs in the database:
– A database manipulation (DML) statement (DELETE,
INSERT, or UPDATE).
– A database definition (DDL) statement (CREATE, ALTER,
or DROP).
– A database operation such as SERVERERROR, LOGON,
LOGOFF, STARTUP, or SHUTDOWN.
17-196
Application and Database Triggers
17-197
Business Application Scenarios
for Implementing Triggers
You can use triggers for:
– Security
– Auditing
– Data integrity
– Referential integrity
– Table replication
– Computing derived data automatically
– Event logging
17-198
Available Trigger Types
17-199
Trigger Event Types and Body
17-200
Creating DML Triggers Using the
CREATE TRIGGER Statement
CREATE [OR REPLACE] TRIGGER trigger_name
timing –- when to fire the trigger
event1 [OR event2 OR event3]
ON object_name
[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW –- default is statement level trigger
WHEN (condition)]]
DECLARE]
BEGIN
... trigger_body –- executable statements
[EXCEPTION . . .]
timing = END [trigger_name];
BEFORE | AFTER | INSTEAD OF
17-201
Specifying the Trigger Firing (Timing)
– BEFORE: Executes 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.
17-202
Statement-Level Triggers
Versus Row-Level Triggers
17-203
Creating DML Triggers Using SQL Developer
17-204
Trigger-Firing Sequence:
Single-Row Manipulation
Use the following firing sequence for a trigger on a table when
a single row is manipulated:
INSERT INTO departments
(department_id,department_name, location_id)
VALUES (400, 'CONSULTING', 2400);
TRG BEFORE statement trigger
17-205
Trigger-Firing Sequence:
Multirow Manipulation
Use the following firing sequence for a trigger on a table when
many rows are manipulated:
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 30;
TRG BEFORE statement trigger
17-206
Creating a DML Statement Trigger Example:
SECURE_EMP
Application
SECURE_EMP trigger
17-208
Using Conditional Predicates
CREATE OR REPLACE TRIGGER secure_emp BEFORE
INSERT OR UPDATE OR DELETE ON employees
BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR(SYSDATE,'HH24')
NOT BETWEEN '08' AND '18') THEN
IF DELETING THEN RAISE_APPLICATION_ERROR(
-20502,'You may delete from EMPLOYEES table'||
'only during normal business hours.');
ELSIF INSERTING THEN RAISE_APPLICATION_ERROR(
-20500,'You may insert into EMPLOYEES table'||
'only during normal business hours.');
ELSIF UPDATING ('SALARY') THEN
RAISE_APPLICATION_ERROR(-20503, 'You may '||
'update SALARY only normal during business hours.');
ELSE RAISE_APPLICATION_ERROR(-20504,'You may'||
' update EMPLOYEES table only during'||
' normal business hours.');
END IF;
END IF;
17-209
END;
Creating a DML Row Trigger
CREATE OR REPLACE TRIGGER restrict_salary
BEFORE INSERT OR UPDATE OF salary ON employees
FOR EACH ROW
BEGIN
IF NOT (:NEW.job_id IN ('AD_PRES', 'AD_VP'))
AND :NEW.salary > 15000 THEN
RAISE_APPLICATION_ERROR (-20202,
'Employee cannot earn more than $15,000.');
END IF;
UPDATEEND;
employees
SET salary = 15500
WHERE last_name = 'Russell';
17-210
Using OLD and NEW Qualifiers
– When a row-level trigger fires, the PL/SQL run-time
engine creates and populates two data structures:
• OLD: Stores the original values of the record processed by the
trigger
• NEW: Contains the new values
– NEW and OLD have the same structure as a record
declared using the %ROWTYPE on the table to which the
trigger is attached.
Data Old Value New Value
Operations
INSERT NULL Inserted value
UPDATE Value before update Value after update
DELETE Value before delete NULL
17-211
Using OLD and NEW Qualifiers: Example
CREATE TABLE audit_emp (
user_name VARCHAR2(30),
time_stamp date,
id NUMBER(6),
old_last_name VARCHAR2(25),
new_last_name VARCHAR2(25),
old_title VARCHAR2(10),
new_title VARCHAR2(10),
old_salary NUMBER(8,2),
new_salary NUMBER(8,2) )
/
CREATE OR REPLACE TRIGGER audit_emp_values
AFTER DELETE OR INSERT OR UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO audit_emp(user_name, time_stamp, id,
old_last_name, new_last_name, old_title,
new_title, old_salary, new_salary)
VALUES (USER, SYSDATE, :OLD.employee_id,
:OLD.last_name, :NEW.last_name, :OLD.job_id,
17-212 :NEW.job_id, :OLD.salary, :NEW.salary);
END;
Using OLD and NEW Qualifiers: Example
17-213
Using the WHEN Clause to Fire a
Row Trigger Based on a Condition
17-215
Managing Triggers Using the
ALTER and DROP SQL Statements
-- Disable or reenable a database trigger:
17-216
Managing Triggers Using SQL Developer
17-217
Viewing Trigger Information
You can view the following trigger information:
17-218
Using USER_TRIGGERS
DESCRIBE user_triggers
17-219
THANKS