PL/SQL PL/SQL is Oracle's Procedural Language extension to SQL. PL/SQL has many programming language...
-
Upload
juliana-knight -
Category
Documents
-
view
313 -
download
0
Transcript of PL/SQL PL/SQL is Oracle's Procedural Language extension to SQL. PL/SQL has many programming language...
PL/SQL
PL/SQL is Oracle's Procedural Language extension to SQL.
• PL/SQL has many programming language features.
• Program units written in PL/SQL can be stored in compiled form.
• PL/SQL code is portable across all operating systems that support Oracle.
• PL/SQL does not support DDL and DCL.
PL/SQL Block
A PL/SQL block contains logically related SQL and PL/SQL statements.
Three sections in a typical PL/SQL block:
• declaration (optional): declare identifiers (variables and constants). • execution (required): execute SQL and
PL/SQL statements.
• exception (optional): perform error handling.
Declaration Section (1)Examples:declare average_GPA number(3,2); no_of_depts constant number(2) := 23; no_of_students number(5) not null := 12000;
employee_name varchar2(30); state_code char(2); done boolean default true;• declare one variable at a time!
Declaration Section (2)PL/SQL Data Types:binary_integer : -231-1 to 231-1natural : 0 to 231
positive : 1 to 231
long : variable length character string up to 32,760 bytes (much shorter than the long type in attribute definition)boolean : boolean type (true, false, null)number(n,m), char(n), varchar2(n) , date : same as their counterparts in SQL
Declaration Section (3)
%type is used to tie the data type of a PL/SQL variable to an existing data type or the data type of an attribute of a relation.
Examples:v_emp_name employee.name%type;v_student_gpa Students.gpa%type;v_course_title Courses.title%type;• using %type leads to more robust code
Declaration Section (4)
PL/SQL Record Type:Example: type course_record_type is record (course_id Courses.cid%type; title Courses.title%type; credit_hours number); course_record course_record_type;• use . to reference record fields course_record.title = ‘Database Systems’;
Declaration Section (5)
%rowtype is used to define a record type variable and tie it to a table structure.
Example:
one_student Students%rowtype;
• one_student can be used to store a tuple of Students at a time.
• one_student.name references to the name attribute.
Execution Section
This section contains executable PL/SQL statements.
• Null Statement
null;
• Assignment Statement
i := i + 1;
name := ‘Smith’;
Conditional Statement (1)
• Conditional Statements:
IF condition THEN
statement1;
-- one or more statements
END IF;
statement2;
/* one or more statements */
PL/SQL Conditions Involving Null
• is null and is not null are as in SQL
Ex: if (course_title is null) then …
• expressions involving a null value will be evaluated to a null
Ex: (s1.gpa > s2.gpa) will be evaluated to null if s1.gpa or s2.gpa is null
• If a condition is evaluated to be false or null, then the corresponding conditional statement will not be evaluated.
Truth Table Involving Null
and true false null or true false null
true true false null true true true true
false false false false false true false null
null null false null null true null null
not true false null
false true null
Conditional Statement (2)
A variation of conditional statement:
IF condition THEN
statement1;
ELSE
statement2;
END IF;
statement3;
Conditional Statement (3)
Another conditional statement: IF condition1 THEN statement1; ELSIF condition2 THEN statement2; ELSE statement3; END IF; statement4;
Sample Program 1 (1)
declare
student_name Students.Name%TYPE;
student_dept Students.Dept_name%TYPE;
begin
select Name, Dept_name
into student_name, student_dept
/* no : needed before host variables */
from Students where SSN = `123456789';
Sample Program 1 (2)
if (student_dept = ‘Computer Science’) then
dbms_output.put_line(`This is a CS student.'); else dbms_output.put_line(`This is not a CS student.'); end if; end;/ /* end each PL/SQL program with / */
Execute PL/SQL Program
• Save the program in a file: sample1.sql
• Execute the program in SQL*Plus
SQL> start sample1
• Enable output to the screen:
SQL> set serveroutput on
or place set serveroutput on at the beginning of the PL/SQL program.
Loop Statement (1)
Simple loop: LOOP statements; EXIT WHEN condition; END LOOP;While loop: WHILE condition LOOP statements; END LOOP;
Sample Program 2declare company_payroll number;begin select sum(salary) into company_payroll from Employees; while company_payroll < 5000000 loop update Employees set salary = salary * 1.02; select sum(salary) into company_payroll from Employees; end loop;end;/
Loop Statement (2)
For loop:
for variable in [reverse] low_value..high_value loop
statements;
end loop;
Examples: for x in -10..10
for x in reverse -10..10
• No need to declare loop variable explicitly.• Loop variable is not accessible outside loop.
• Modifying loop variable will cause an error.
Exception Section
• An exception is any error that occurs during program execution.• Syntax of error handling:– for specific exceptions
when exception_name then error-handling-code;– for unspecified exceptions
when others then error-handling-code;
System Pre-defined Exceptions
Examples: invalid_cursor: sqlcode = -1001 too_many_rows: sqlcode = -1422 dup_val_on_index: sqlcode = -1 no_data_found: sqlcode = +100• Each system exception has an error
message, stored in sqlerrm.• System exceptions are raised
automatically by PL/SQL.
An Example
exception /* exception section */
when dup_val_on_index then
dbms_output.put_line(sqlcode ||
‘--’ || sqlerrm);
end;
Output message if the exception occurs:
-1--ORA-00001: unique constraint violated
More on Pre-defined Exceptions
exception name Oracle error number cursor_already_open ORA-06511 dup_val_on_index ORA-00001 invalid_cursor ORA-01001 no_data_found ORA-01403 rowtype_mismatch ORA-06504 storage_error ORA-06500 too_many_rows ORA-01422 not_logged_on ORA-01012 login_denied ORA-01017
User-Defined Exceptions
• User-defined exceptions need to be explicitly declared.
exception_name exception;
• User-defined exceptions need to be raised by the user.
raise exception_name;
An Exampledeclare /* declare section */ invalid_gpa exception;begin /* execution section */ if (gpa < 0 or gpa > 4.0) then raise invalid_gpa; end if;exception /* exception section */ when invalid_gpa then dbms_output.put_line(‘GPA value is invalid.’);end;/
Exception Handling Recommendation
• It is a good practice to handle all exceptions explicitly and to handle them in the exception section.
–Can improve reliability and readability
Different Types of Blocks
• Anonymous Blocks (unnamed blocks)• Procedures procedure proc_name [parameters] is
[declaration] begin …
• Functions function func_name [parameters]
return data_type is
[declaration] begin …
Example of An Anonymous Blockdeclare company_payroll number;begin select sum(salary) into company_payroll from Employees; while company_payroll < 5000000 loop update Employees set salary = salary * 1.02; select sum(salary) into company_payroll from Employees; end loop;end;/
Procedure
procedure procedure_name
[(parameter, parameter, …, parameter)] is
[local declarations]
begin
execution section;
[exception section]
end;
parameter definition:
parameter_name [in | out | in out] data_type
Sample Program 3 (1)
set serveroutput ondeclare v_cid customers.cid%type; v_cname customers.cname%type; v_city customers.city%type; status boolean; procedure get_customer( cust_id in customers.cid%type, cust_name out customers.cname%type, cust_city out customers.city%type, status out boolean) is
Sample Program 3 (2)
begin select cname, city into cust_name, cust_city from customers where cid = cust_id; status := true; exception when no_data_found then status := false; end;begin v_cid := ‘c001’; get_customer(v_cid, v_cname, v_city, status);
Sample Program 3 (3)
if (status) then
dbms_output.put_line(v_cid || ‘ ‘ ||
v_cname || ‘ ‘ || v_city); else
dbms_output.put_line(‘Customer ‘ ||
v_cid || ‘ not found’); end if;end;/
Sample Program 4 (1)
set serveroutput ondeclare v_city customers.city%type; customer_no number; function no_of_customers( cust_city in customers.city%type) return number is num_of_customers number; begin select count(*) into num_of_customers from customers where city = cust_city;
Sample Program 4 (2)
return (num_of_customers); end;begin v_city := ‘Dallas’; customer_no := no_of_customers(v_city); dbms_output.put_line(‘Number of customers in ’ || v_city || ‘ is ‘ || customer_no);end;/
Stored Procedure and Function (1)
• procedure or function definitions can be stored for later use (in SQL and other PL/SQL blocks).• Stored procedures/functions are stored
in compiled form.• Stored procedures and functions are
created by create or replace procedure proc_name … create or replace function func_name …–only in parameter allowed for function.
An Exampleset serveroutput oncreate or replace procedure get_cus_name( v_cust_id in customers.cid%type) is v_cust_name customers.cname%type;begin select cname into v_cust_name from customers where cid = v_cust_id; dbms_output.put_line(‘Customer name: ‘ || v_cust_name); end;/show errors
Stored Procedure and Function (2)
• Compile stored procedure in file proc.sql
SQL> start proc
show errors displays errors detected during compiling the procedure.
• Execute stored procedure get_cus_name
SQL> execute get_cus_name(‘c001’);
Package
• A package is a group of related PL/SQL objects (variables, …), procedures, and functions.
• Each package definition has two parts:–package specification–package body
• Package specification provides an interface to the users of the package.
• Package body contains actual code.
Package Specification (1)
create or replace package banking as function check_balance (account_no in Accounts.acct_no%type) return Accounts.balance%type; procedure deposit (account_no in Accounts.acct_no%type, amount in Accounts.balance%type);
Package Specification (2)
procedure withdraw (account_no in Accounts.acct_no%type, amount in Accounts.balance%type);end;/show errors
Package Body (1)
create or replace package body banking as function check_balance (account_no in Accounts.acct_no%type) return Accounts.balance%type is acct_balance Accounts.balance%type; begin select balance into acct_balance from Accounts where acct_no = account_no; return acct_balance; end;
Package Body (2)
procedure deposit (account_no in Accounts.acct_no%type, amount in Accounts.balance%type) is begin if (amount <= 0) then dbms_output.put_line(‘Wrong amount.’); else update Accounts set balance = balance + amount where acct_no = account_no; end if; end;
Package Body (3)
procedure withdraw (account_no in Accounts.acct_no%type, amount in Accounts.balance%type) is acct_balance Accounts.balance%type;
Package Body (4)
begin acct_balance := check_balance(account_no); if (amount > acct_balance) then dbms_output.put_line(‘Insufficient fund.’); else update Accounts set balance = balance - amount where acct_no = account_no; end if; end;end; /* end of the package body *//show errors
Public versus Private Constructs
• Public constructs of a package are listed in the package specification.
• Private constructs are listed in the package body but not in package specification.
• Public constructs can be accessed by others.
• Private constructs can only be accessed by other constructs in the same package.
Example: If we remove the definition of the check_balance function from the banking package specification, it becomes private.
Use of Package
• Objects defined in a package specification can be used in other packages, PL/SQL blocks and SQL queries.
• Compile the package–SQL> start packspec1 (or @packspec1)–SQL> start packbody1
• May use execute to invoke a package.
SQL> execute banking.deposit(100, 200);
SQL> execute banking.withdraw(200, 500);
Use of a Stored Function
• Declare a variable
SQL> var bal number
• Execute the function
SQL> execute :bal :=
banking.check_balance(200);
• Print the value
SQL> print bal
Related Data Dictionary Information (1)
select object_name, object_type, created
from user_objects
where object_type = ‘PACKAGE’;
OBJECT_NAME OBJECT_TYPE CREATED---------------------- --------------------- --------------BANKING PACKAGE 07-SEP-98
Related Data Dictionary Information (2)
• To see the source code of a user_defined object, use the following SQL query:
select text
from user_source
where name = ‘BANKING’;
• Both specification and body will be shown.
Cursor in PL/SQL (1)
• If a query may result in more than one tuple, a cursor needs to be used.
• Define a cursor:
cursor cursor_name is select_statement;Example: cursor c1 is select cid, cname, city from customers;
Working with Cursor (1)
• open cursor_name;
• fetch cursor_name
into record_or_variable-list;
• close cursor_name;
Working with Cursor (2)
declare cursor c1 is select cid, cname, city from customers; c1_rec c1%rowtype;/* %rowtype is used to define a PL/SQL record type that corresponds to the schema of a table.*/
Working with Cursor (3)
begin open c1; fetch c1 into c1_rec; dbms_output.put_line(c1_rec.cid || ‘, ‘ || c1_rec.cname || ‘, ‘ || c1_rec.city); close c1;end;/
Cursor Attributes
• c1%notfound returns true if the most recent fetch failed to obtain a row.
• c1%found returns true if the most recent fetch obtained a row.
• c1%rowcount returns the total number of rows fetched so far.
• c1%isopen returns true if cursor c1 is open.
Using Cursor Attributesbegin if (not c1%isopen) then open c1; end if; fetch c1 into c1_rec; while c1%found loop dbms_output.put_line(c1_rec.cid || ‘, ‘ || c1_rec.cname || ‘, ‘ || c1_rec.city); fetch c1 into c1_rec; end loop; close c1;end;/
Cursor For Loop
begin for c1_record in c1 loop if (c1_record.city = ‘New York’) then dbms_output.put_line(c1_record.cid || ‘, ‘ || c1_record.cname || ‘, ‘ ||
c1_record.city); end if; end loop;end;/• open, fetch and close are all done implicitly.• No need to declare c1_record.
Cursor for Update (1)
• Use the for update clause to declare cursor: cursor c1 is select cid, cname, city from customers for update;• Use of the cursor. update customers set city = ‘Boston’ where current of c1;
delete from customers where current of c1;
Cursor for Update (2)
declare cursor c1 is select * from customers for update;begin for c1_rec in c1 loop if (c1_rec.city = ‘New York’) then delete from customers where current of c1; end if; end loop;end;
Parameterized Cursor
cursor cursor_name (parameter_list) is select_statement;
Example:
cursor c1(d_name in Students.dept_name%type) is
select age, avg(GPA) from Students
where dept_name = d_name
group by age;
open c1(‘Computer Science’);
Built-in Package: dbms_output (1)
• dbms_output is primarily used to help debugging PL/SQL programs.
• dbms_output has the following public procedures:
– disable (dbms_output.disable;): It disables
the dbms_output package.
– enable: It enables the dbms_output package. Use dbms_output.enable(20000);
to set the buffer size to be 20,000 bytes. The
default buffer size is 2,000.
Built-in Package: dbms_output (2)
–put_line( ): puts information into the buffer and starts a new line.
–put( ): puts information into the buffer.
–new_line: starts a new line.
– get_line(line, status): retrieves one line of information from the buffer and stores the information in variable line.
• status = 0 if successful
• status = 1 if unsuccessful
Trigger (1)
• A trigger is an event-driven block of PL/SQL code.
• An event could be an insertion of a tuple into a table, a deletion of an existing tuple from a table, and an update of a table.
• A trigger fires (executes, activates) when an event occurs.
• Triggers are useful for enforcing various integrity constraints and business rules.
Trigger (2)
ECA Model:
Event Condition Action
an eventdetected?
Is the eventsignificant?
take actions
yes yes
insert deleteupdate
need to satisfy additional condition
executeSQL/PLblock
Trigger (3)
create or replace trigger raise_sal before update of salary on employees for each row when (new.salary > old.salary * 1.2) begin dbms_output.put_line(‘Old salary is ‘ || :old.salary || ‘, ‘ || ‘New salary is ‘ || :new.salary); dbms_output.put_line(‘The raise is too high!’); end;
Trigger (4)
• Trigger event update of salary on employees insert on employees delete or insert on employees
• trigger timing
before: fires the trigger before executing the triggering statement
after: fires the trigger after executing the triggering statement
Trigger (5)
• row trigger
– for each row is specified
– fire the trigger once for each row that is affected by the event and satisfies the additional condition in the when clause
• statement trigger
– for each row is not specified
– fire the trigger once for the entire trigger event
Trigger (6)
• trigger restriction for row trigger when new.salary > old.salary * 1.2–new is applicable for insert and update
–old is applicable for update and delete–use :new.salary and :old.salary in trigger
body
• trigger body– the PL/SQL block containing trigger
action.
Trigger(7)
create or replace trigger raise_salafter delete on employeesdeclare total_sal number;begin select sum(salary) into total_sal from employees; dbms_output.put_line(‘The new total salary is ’ || total_sal); end;
Trigger Applications (1)
• Use trigger for monitoring changesExample: add a log entry each time the price
of a product is changed log table for product: create table products_log (pid char(4), username char(10), update_date date, old_price number(6, 2), new_price number(6, 2));
Trigger Applications (2)
create or replace trigger update_p_price
after update of price on products
for each row
begin
insert into products_log values
(:old.pid, user, sysdate, :old.price, :new.price);
end;
Trigger Applications (3)
• Use trigger to enforce integrity constraints
Example: If a student is removed, delete all enrollments by the student.
create or replace trigger stud_enroll
after delete on students
for each row
begin
delete from enrollments where sid = :old.sid;
end;