Lecture6 4-PLSQL2
Lecture6 4-PLSQL2
and Auditing
Oracle PL/SQL: Triggers
1
Triggers
3
Triggers
referencing specifies correlation names that
can be used to refer to the old and new
values of the row components that are being
affected by the trigger
for each row designates the trigger to be a
row trigger, i.e., the trigger is fired once for
each row that is affected by the triggering
event and meets the optional trigger
constraint defined in the when clause.
when specifies the trigger restriction.
4
Trigger example
A trigger is executed when a row is inserted
into the odetails table.
The trigger checks to see if the quantity
ordered is more than the quantity on hand.
If it is, an error message is generated, and
the row is not inserted.
Otherwise, the trigger updates the quantity
on hand for the part and checks to see if it
has fallen below the reorder level. If it has,
it sends a row to the restock table indicating
that the part need to be reordered.
5
Trigger example
trig2.sql
trig2test.sql
6
Trigger example (2)
The trigger is defined on the parts
table and is triggered when the price
column is updated. Each time
someone updates the price of a
particular part, the trigger makes an
entry in a log file of this update along
with the userid of the person
performing the update and the date of
the update.
7
Trigger example (2)
trig3.sql
SQL>update parts set price = 55.00
where pno = 1099;
SQL> select * from parts_log;
Use trig_tables.sql to test trig3.sql
9
Database Access Using
Cursors
10
Database Access Using
Cursors
When the result of an SQL query
(select statement) consists of more
than one row, the simple select into
statement can not be used.
A PL/SQL cursor allows the program to
fetch and process information from the
database into the PL/SQL program,
one row at a time.
11
Explicit Cursor
Explicit cursor: used for processing a
query resulting in more than one row.
Implicit cursor: is automatically defined
by PL/SQL for the select into statements,
which result in one or fewer rows.
cursor c2 is
select pno, pname, price*markdown
sale_price
from parts Use PL/SQL variable
markdown 13
Process cursor
open <cname>;
fetch <cname> into <Record-or-VariableList>;
close <cname>;
14
Explicit Cursor Attributes
BEGIN
open c; Here the
fetch c into sailorData; first row of
sailors is
inserted into
16
sailorData
Cursor Example
RAD_VALS DECLARE
DECLARE
PiPiconstant
constantNUMBER(8,7)
NUMBER(8,7):= :=3.1415926;
3.1415926;
area
areaNUMBER(14,2);
NUMBER(14,2);
cursor
cursorrad_cursor
rad_cursorisisselect
select**from
fromRAD_VALS;
radius rad_val
RAD_VALS;
Rad_cursor rad_valrad_cursor%ROWTYPE;
rad_cursor%ROWTYPE;
3 BEGIN
BEGIN
f open
openrad_cursor;
rad_cursor;
e 6
fetch
fetchrad_cursor
rad_cursorinto
intorad_val;
rad_val;
area:=pi*power(rad_val.radius,2);
area:=pi*power(rad_val.radius,2);
t insert
insertinto
intoAREAS
AREASvalues
values(rad_val.radius,
(rad_val.radius,area);
area);
c 8 close rad_cursor;
close rad_cursor;
END;
END;
h //
Rad_val
AREAS
Radius Area 17
3 28.27
DECLARE
DECLARE DECLARE
DECLARE
…… ……
cursor
cursorrad_cursor
rad_cursorisisselect
select**from
fromRAD_VALS; cursor
rad_val rad_cursor%ROWTYPE;
RAD_VALS; cursorrad_cursor
rad_cursorisisselect
select**from
fromRAD_VALS;
RAD_VALS;
rad_val rad_cursor%ROWTYPE; rad_val RAD_VALS.radius%TYPE;
BEGIN rad_val RAD_VALS.radius%TYPE;
BEGIN BEGIN
open
openrad_cursor;
rad_cursor; BEGIN
fetch open
openrad_cursor;
rad_cursor;
fetch rad_cursorinto
rad_cursor intorad_val;
rad_val;
area:=pi*power(rad_val.radius,2);
area:=pi*power(rad_val.radius,2); fetch
fetchrad_cursor
rad_cursorinto
intorad_val;
rad_val;
insert
insertinto
intoAREAS
AREASvalues
values(rad_val.radius,
(rad_val.radius, area:=pi*power(rad_val,2);
area:=pi*power(rad_val,2);
area); insert
area); insertinto
intoAREAS
AREASvalues
values(rad_val,
(rad_val,area);
area);
…… ……
DECLARE
DECLARE DECLARE
DECLARE
…… ……
cursor
cursorrad_cursor
rad_cursorisisselect
select**from
fromRAD_VALS;
RAD_VALS; cursor
cursorrad_cursor
rad_cursorisisselect
selectradius
radiusfrom
from
rad_val
rad_valRAD_VALS%ROWTYPE;
RAD_VALS%ROWTYPE;
BEGIN RAD_VALS;
RAD_VALS;
BEGIN
open rad_val
rad_valRAD_VALS.radius%TYPE;
openrad_cursor;
rad_cursor; RAD_VALS.radius%TYPE;
fetch BEGIN
fetch rad_cursorinto
rad_cursor intorad_val;
rad_val; BEGIN
area:=pi*power(rad_val.radius,2); open
openrad_cursor;
rad_cursor;
area:=pi*power(rad_val.radius,2);
insert fetch
fetch rad_cursorinto
rad_cursor intorad_val;
insertinto
intoAREAS
AREASvalues
values(rad_val.radius,
(rad_val.radius, rad_val;
area);
area); area:=pi*power(rad_val,2);
area:=pi*power(rad_val,2);
…… insert
insertinto
intoAREAS
AREASvalues
values(rad_val,
(rad_val,area);
area);…
…
18
Cursor Example
Use of the cursor statements and
attributes
p7.sql
19
Cursor for loop
This loop is very useful when all rows of the
cursors are to be processed.
for <record_index> in <cname> loop
<loop-body>;
end loop;
<record_index> is a record variable that is
implicitly declared by PL/SQL. Its scope is
the for loop, and it can not be accessed
outside the for loop.
20
Cursor for loop
21
Cursor for loop example
declare
cursor c1 is c1_rec
select cno, cname, city No declare for the
from customers, zipcodes record into which the
where customers.zip = zipcodes.zip; cursor rows are to be
fetched
begin
for c1_rec in c1 loop
dbms_output.put-line(‘Row number ’ || c1%rowcount
|| ‘> ‘ || c_rec.cno || ‘ ‘ || c1-rec.cname || ‘ ‘ ||
c1_rec.city);
end loop
end;
22
Parameterized Cursors
27
Cursor variables
Cursor variables are not required to have
the SQL select statement associated with
them at the time of their declaration.
Different SQL select statements can be
associated with cursor variables at
different times.
type <cursor-var-type-name> is ref cursor
[return <return-type>];
28
Cursor variables example
30
Records
Table-based records, whose structure is
the same as that of a row in a database
table. p10.sql
Cursor-based records is based on the
select list of a cursor. p11.sql
Programmer defined records. A type
declaration is needed before record
variables can be declared. p12.sql
31
Table-based records
DECLARE
customer_rec customers%rowtype;
BEGIN
select *
into customer_rec
from customers
where cno = '4444';
if (customer_rec.phone is null) then
dbms_output.put_line('Phone number is absent');
else
dbms_output.put_line('Phone number is ' || customer_rec.phone);
end if;
END;
/
32
Cursor-based records
DECLARE
cursor c1 is BEGIN
select orders.eno employee_no, open c1;
ename employee_name, loop
sum(price*qty) total_sales fetch c1 into emp_sales_rec;
from exit when c1%NOTFOUND;
employees,orders,odetails,parts dbms_output.put_line(
where employees.eno = emp_sales_rec.employee_no || '
orders.eno ' || emp_sales_rec.employee_name ||
and ' ' || emp_sales_rec.total_sales);
orders.ono = odetails.ono end loop;
and close c1;
odetails.pno = parts.pno END;
group by orders.eno, ename; /
emp_sales_rec c1%rowtype;
33
Programmer defined records
DECLARE
TYPE my_rec_type IS RECORD
(number integer,
name varchar2(20));
r1 my_rec_type;
r2 my_rec_type;
BEGIN
r1.number := 111;
r1.name := 'jones';
r2 := r1;
dbms_output.put_line('Number = ' || r2.number ||
' Name = ' || r2.name);
END;
/
34
PL/SQL Tables
35
Operations of tables
count returns the number of elements in the
table. n := the_table.count;
delete deletes the specified row or all rows.
the_table.delete(43);
exists returns true if there exists a row in the
specified index, otherwise, it returns false. If
the_table.exists(3) then …
first returns the lowest-valued index
last returns the highest-valued index
next returns the next-higher-valued index
prior returns the next-lower-valued index
36
Table example
Retrieves information from the Oracle data
dictionary table user_tab_columns and
prints the relational schemas of tables
whose names start with the letter “Z”
p13.sql
SQL> start p10
37
Built-In Packages
38
dbms_output package
dbms_output package allows the user
to display information to the session’s
output device as the PL/SQL program
executes.
disable all calls to the dbms_output
package.
dbms_output.disable
SQL> set serverouput off
39
dbms_output package
42
dbms_sql Package
Executing Queries
– Open the cursor
– Parse the statement
– Bind any input variables
– Define the output variables
– Execute the query
– Fetch the rows
– Return the results to PL/SQL variables
– Close the cursor
43
dbms_sql Package
p20.ql creates a package dsql with two
procedures get_columns and
get_query_results.
p21.sql creates a package dsql_driver with
two procedures and uses the types and
procedures get_columns and
get_query_results in p20.sql.
p22.sql is an anonymous PL/SQL block that
calls procedures drive_get_query_results
from package dsql_driver in p21.sql
44
Error Handling
PL/SQL implements run-time error handling
via exceptions and exception handlers.
when <exception-name> then
<Error-Handling-Code>
User defined exception
p40.sql
SQL> execute insert_odetails(1234, 1111, -5);
– 'Quantity is invalid'
SQL> execute insert_odetails(2000, 10900, 10);
SQL> execute insert_odetails(2000, 11001, 10);
– 'PRIMARY KEY VIOLATION'
46
Exercises
Try all the following triggers:
– trig1.sql; trig2.sql; trig2test.sql; trig3.sql; trig_tables.sql
(SQL script for creating tables for the triggers).
Try all the following cursors:
– p7.sql; p8.sql (Updatable Cursor); p9.sql (Cursor Variable)
Try all the following tables:
– p10.sql (Table-based record); p11.sql (Cursor-based
record); p12.sql (Programmer-defined record)
Try the table: p13.sql
47
Exercises