Working With Composite Data Types: L/O/G/O
Working With Composite Data Types: L/O/G/O
Data Types
L/O/G/O
Objectives
After completing this lesson, you should be able to do
the following:
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
Describe the differences among records, tables, and
tables of records
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 3GL 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
identifier
type_name;
field_declaration:
field_name {field_type | variable%TYPE
| table.column%TYPE | table%ROWTYPE}
[[NOT NULL] {:= | DEFAULT} expr]
Example
Field1 (data type)
100
King
AD_PRES
ROWTYPE Attribute%
Declare a variable according to a collection of columns in
a database table or view.
Prefix %ROWTYPE with the database table or view.
Fields in the record take their names and data types from
the columns of the table or view.
Syntax:
DECLARE
identifier reference%ROWTYPE;
ROWTYPE Attribute%
...
DEFINE employee_number = 124
DECLARE
emp_rec
employees%ROWTYPE;
BEGIN
SELECT * INTO emp_rec FROM employees
WHERE employee_id = &employee_number;
INSERT INTO retired_emps(empno, ename, job, mgr,
hiredate, leavedate, sal, comm, deptno)
VALUES (emp_rec.employee_id, emp_rec.last_name,
emp_rec.job_id,emp_rec.manager_id,
emp_rec.hire_date, SYSDATE, emp_rec.salary,
emp_rec.commission_pct, emp_rec.department_id);
END;
/
...
DEFINE employee_number = 124
DECLARE
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 emp_rec FROM employees
WHERE employee_id = &employee_number;
INSERT INTO retired_emps VALUES emp_rec;
END;
/
SELECT * FROM retired_emps;
SET SERVEROUTPUT ON
SET VERIFY OFF
DEFINE employee_number = 124
DECLARE
emp_rec retired_emps%ROWTYPE;
BEGIN
SELECT * INTO emp_rec FROM retired_emps;
emp_rec.leavedate:=SYSDATE;
UPDATE retired_emps SET ROW = emp_rec WHERE
empno=&employee_number;
END;
/
SELECT * FROM retired_emps;
:employees
...
TYPE ename_table_type IS TABLE OF
employees.last_name%TYPE
INDEX BY PLS_INTEGER;
...
ename_table ename_table_type;
Value
...
1
5
3
Jones
Smith
Maduro
...
...
PLS_INTEGER
Scalar
EXISTS
COUNT
FIRST and LAST
PRIOR
NEXT
DELETE
Nested Tables
2 GB
Bombay
Sydney
Oxford
4
..
London
....
VARRAY
Bombay
Sydney
Oxford
4
..
London
....
10
Tokyo
Using Explicit
Cursors
L/O/G/O
Objectives
After completing this lesson, you should be able to do the
following:
Distinguish between implicit and explicit cursors
Discuss the reasons for using explicit cursors
Declare and control explicit cursors
Use simple loops and cursor FOR loops to fetch data
Declare and use cursors with parameters
Lock rows with the FOR UPDATE clause
Reference the current row with the WHERE CURRENT
clause
Cursors
Every SQL statement executed by the Oracle server has
an associated individual cursor:
Implicit cursors: Declared and managed by PL/SQL
for all DML and PL/SQL SELECT statements
Explicit cursors: Declared and managed by the
programmer
Table
100 King
Active set
AD_PRES
139 Seo
ST_CLERK
140 Patel
ST_CLERK
DECLARE
OPEN
FETCH
active set.
current
row into
variables.
EMPTY?
Yes
Test for
existing
rows.
Return to
FETCH if
rows are
found.
CLOSE
Release the
active set.
Fetch a row.
Cursor
pointer
Cursor
pointer
CURSOR cursor_name IS
select_statement;
Examples
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
DECLARE
locid NUMBER:= 1700;
CURSOR dept_cursor IS
SELECT * FROM departments
WHERE location_id = locid;
...
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
...
BEGIN
OPEN emp_cursor;
SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
empno employees.employee_id%TYPE;
lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO empno, lname;
DBMS_OUTPUT.PUT_LINE( empno ||' '||lname);
...
END;
/
...
LOOP
FETCH emp_cursor INTO empno, lname;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( empno ||' '||lname);
END LOOP;
CLOSE emp_cursor;
END;
/
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_record;
...
Type
Description
%ISOPEN
Boolean
Boolean
Boolean
Number
%NOTFOUN
D
%FOUND
%ROWCOUN
T
ISOPEN Attribute%
Fetch rows only when the cursor is open.
Use the %ISOPEN cursor attribute before performing
a fetch to test whether the cursor is open.
Example
SET SERVEROUTPUT ON
BEGIN
FOR emp_record IN (SELECT employee_id, last_name
FROM employees WHERE department_id =30)
LOOP
DBMS_OUTPUT.PUT_LINE( emp_record.employee_id ||'
'||emp_record.last_name);
END LOOP;
END;
/
when the
cursor is opened and the query is executed.
Open an explicit cursor several times with a
different active set each time.
OPEN
cursor_name(parameter_value,.....) ;
SET SERVEROUTPUT ON
DECLARE
CURSOR
emp_cursor (deptno NUMBER) IS
SELECT employee_id, last_name
FROM
employees
WHERE
department_id = deptno;
dept_id NUMBER;
lname
VARCHAR2(15);
BEGIN
OPEN emp_cursor (10);
...
CLOSE emp_cursor;
OPEN emp_cursor (20);
...
duration of a transaction.
Lock the rows before the update or delete.
UPDATE employees
SET
salary = ...
WHERE CURRENT OF emp_cursor;
Handling
Exceptions
L/O/G/O
Objectives
After completing this lesson, you should be
able to do the following:
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
SET SERVEROUTPUT ON
DECLARE
lname VARCHAR2(15);
BEGIN
SELECT last_name INTO lname FROM employees WHERE
first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is : '
||lname);
END;
/
Example of an Exception
SET SERVEROUTPUT ON
DECLARE
lname VARCHAR2(15);
BEGIN
SELECT last_name INTO lname FROM employees WHERE
first_name='John';
DBMS_OUTPUT.PUT_LINE ('John''s last name is : '
||lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (' Your select statement
retrieved multiple rows. Consider using a
cursor.');
END;
/
Handling Exceptions
Is the
exception
trapped?
No
Terminate
abruptly.
Yes
Exception Execute statements
is raised. in the EXCEPTION
section.
Terminate
gracefully.
Propagate the
exception.
Exception Types
Predefined Oracle server
Non-predefined Oracle server
User-defined
Implicitly raised
Explicitly raised
Trapping Exceptions
Syntax:
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
statement2;
. . .
[WHEN exception3 [OR exception4 . . .] THEN
statement1;
statement2;
. . .]
[WHEN OTHERS THEN
statement1;
statement2;
. . .]
Trapping Non-Predefined
Oracle Server Errors
Declare
Associate
Declarative section
Name the
exception.
Use PRAGMA
EXCEPTION_INIT.
Reference
EXCEPTION section
Handle the raised
exception.
Non-Predefined Error
To trap Oracle server error number 01400
(cannot insert NULL):
SET SERVEROUTPUT ON
DECLARE
1
2
insert_excep EXCEPTION;
PRAGMA EXCEPTION_INIT
(insert_excep, -01400);
BEGIN
Declare
Raise
Reference
Declarative
section
Executable
section
Exception-handling
section
Name the
exception.
Explicitly raise
the exception by
using the RAISE
statement.
Calling Environments
iSQL*Plus
Precompiler
application
An enclosing
PL/SQL block
DECLARE
. . .
no_rows
exception;
integrity
exception;
PRAGMA EXCEPTION_INIT (integrity, -2292);
BEGIN
FOR c_record IN emp_cursor LOOP
BEGIN
SELECT ...
UPDATE ...
IF SQL%NOTFOUND THEN
RAISE no_rows;
END IF;
END;
END LOOP;
EXCEPTION
WHEN integrity THEN ...
WHEN no_rows THEN ...
END;
/
RAISE_APPLICATION_ERROR Procedure
Syntax:
raise_application_error (error_number,
{TRUE
| FALSE}]);
You can use message[,
this procedure
to issue
user-defined error
RAISE_APPLICATION_ERROR Procedure
RAISE_APPLICATION_ERROR Procedure
Executable section:
BEGIN
...
DELETE FROM employees
WHERE manager_id = v_mgr;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,
'This is not a valid manager');
END IF;
...
:Exception
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR (-20201,
'Manager is not a valid employee.');
END;
/
section
!Thank You
L/O/G/O