Vous êtes sur la page 1sur 35

Oracle Advanced PL-SQL

CSCI 4227 Advanced DBMS


Overview
Parameter Passing (review)
Error Handling (review)
Packages
Specification
Body
Package Variables
Execution Rights
Collections (Aggregates)
Dynamic SQL
Nested Blocks
Bulk Binds
Returning
Other Functions
Parameter Passing
Can be positional or named
Consider the function
my_proc(one Number, two Varchar2, three Number)
Can call as
My_proc(1,hi,2)
My_proc(one=>1, three=>2,two=>hi)
In positional only the last N arguments can take
default values
In named this restriction does not apply
Parameter Default Values
Consider the procedure
my_proc(one Number, two Varchar2)
You can specify default values
-my_proc( one Number DEFAULT 5,
two Varchar2 DEFAULT yes)
Parameter Types
IN
Value must be provided for this parameter. The
function can not change this value.
OUT
The item passed must be a variable in the scope of the
calling procedure. This parameter can be assigned a
value in the function but not used. When the function
terminates the value in the variable is changed
IN OUT
Can be read/written within procedure, and will update
the variable passed in the calling procedure when the
function terminates.
EXCEPTIONS
EXCEPTION section at the end of a
Procedure/Function for error handling
A Throw-Catch paradigm without the Try block
Thrown anywhere in program
Caught in exception section
Can handle system defined errors or user defined
errors
Each error must have a separate WHEN clause in
the EXCEPTION section
Defining Errors
Several Predefined
Execution Errors raised by the system
Or Define your own in the declaration
section
my_error_type exception;
Pre-Defined Errors
ZERO_DIVIDE
CASE_NOT_FOUND
INVALID_CURSOR
NO_DATA_FOUND
TOO_MANY_ROWS
VALUE_ERROR
STORAGE_ERROR
INVALID_NUMBER
CURSOR_ALREADY_OPEN

TIMEOUT_ON_RESOURCE
ROWTYPE_MISMATCH
PROGRAM_ERROR
LOGIN_DENIED
NOT_LOGGED_ON
DUP_VAL_ON_INDEX
TRANSACTION_BACKED_
OUT
Raising Errors
Explicitly with RAISE(err_name)
By the system executing your database
commands
Using Exceptions
declare
-- exceptions
Exception_I_am_Lost exception;
begin
dbms_output.put_line('This is a test');
raise Exception_I_am_Lost;
dbms_output.put_line('This should never print');
exception
when ZERO_DIVIDE then
dbms_output.put_line('You can not divide by zero');
when Exception_I_am_Lost then
dbms_output.put_line('The program is Lost');
when OTHERS then
dbms_output.put_line('An error I can not cope with');
end;
Packages
Groups of related functions, procedures and
initialization code
Borrowed from ADA
as were named parameters
Similar in concept to a class
You have been using one
DBMS_OUTPUT

Package Contents
CREATE OR REPLACE my_package
Package Specification
Declare the Procedures, Functions, Variables,
Types, Exceptions and Cursors for the package
Package Body
Define these items
Package Variables
Variables defined/initialized in package
Specification are accessible within and without the package
Body are private to the package.
All functions/procedures share one copy
Initialized when a user session first uses the package
Not shared between users sessions
Not retained after sessions terminated
Can be used like class variables in C++/VB

CREATE PACKAGE BODY base_stat AS
number_pers INT := 0;

Here the variable: number_pers is accessible to all functions in
PACKAGE base_stat. But not outside
Initialization
Packages are initialized ONCE per session
When you first use a package in a session
Any Package Level variables are initialized
They hold their values until your session
terminates
They are NOT shared with other users of the
package.
Access Rights
Unless otherwise specified Stored PL-SQL
(Procedures, Functions, Triggers and
Packages) execute using the rights of the
OWNER of the package not the executor
The AUTHID clause can override this.
AUTHID DEFINER
AUTHID CURRENT_USER
Using AUTHID
CREATE [OR REPLACE] FUNCTION
[schema_name.]function_name
[(parameter_list)] RETURN datatype
[AUTHID {CURRENT_USER | DEFINER}] {IS | AS}
-- standalone procedure

-- package spec
CREATE [OR REPLACE] PACKAGE
[schema_name.]package_name
[AUTHID {CURRENT_USER | DEFINER}] {IS | AS}
Collections (Aggregates)
Same as in any programming language
Multi-Dimensional collections created by nesting types
Requires you to define a type then instantiate it to use it
Needed when you need to access several rows at once
Arrays
Have elements 1Size available for use at all times.
All elements allocated at creation
Tables
Can have any number of elements
Storage only allocated for indexes used
Indexes need not be consecutive
VARRAY
declare
type Score_List is vararry(50) of integer;
Test_Scores Score_List;

Indexed by a binary integer
Must be Initialized by a call to a constructor
Test_Scores := Score_List(0,0,0,0,0,0,0,0,0,0)
Referenced by subscript
Test_Scores(4) := 98;
Example of Varray
create or replace procedure CollectionDemo1 (val
integer)
as
type score_list is VARRAY(20) OF integer;
vals score_list;
begin
vals:=score_list(0,1,2,3,4,5,6,7,8,9);
dbms_output.put_line('hi there '||vals(val));
end;
/
TABLE OF
declare
Type Name_Table is table of VARCHAR2(20);
SHIP_NAMES Name_Table:=Name_Table();

Indexed by binary integer
Elements not allocated until an item is inserted
Referenced by subscript
Subscripts need not be sequential
SHIP_NAMES.extend;
SHIP_NAMES(4) := Kobayashi Maru
Example of Table
create or replace procedure CollectionDemo2
as
type name_table is table of VARCHAR2(10);
names name_table:=name_table();
sub integer;
begin
sub:=0;
for row in (select lname from Staff order by lname)
loop
sub:=sub+1;
names.extend;
names(sub):=row.lname;
end loop;
dbms_output.put_line('Descending...........');
for sub in reverse 1..names.count
loop
dbms_output.put_line('hi there '||names(sub));
end loop;
end;
/
Defining Collections
Arrays
TYPE type_name IS {VARRAY | VARYING ARRAY} (
size_limit) OF element_type [NOT NULL];

Tables
TYPE type_name IS TABLE OF element_type [NOT NULL]
INDEX BY [BINARY_INTEGER | PLS_INTEGER |
VARCHAR2(size_limit)]; INDEX BY key_type;
Dynamic SQL
PL-SQL supports
Queries/Cursors
DML
PL-SQL does not support
SQL where the TABLES involved are not known
beforehand
DDL
This is what the EXECUTE IMMEDIATE is
used for
Embedded SQL Syntax
EXECUTE IMMEDIATE dynamic_string
[INTO {define_variable[, define_variable]... | record}]
[USING [IN | OUT | IN OUT] bind_argument
[, [IN | OUT | IN OUT] bind_argument]...]
[{RETURNING | RETURN} INTO bind_argument[,
bind_argument]...];
Embedded SQL Examples
Execute immediate create table SHUTTLE
(NCC varchar2(20), ID Number);

Stmt := insert into VISIT values (NX2000,
Iota, 07-NOV-2285,11-DEC-2285)
Execute immediate Stmt;
Execute immediate insert into PLANET values
(:1,:2,:3) using RuraPenthe, 2, 3;



Using into to get values back
declare
Registry STARSHIP.REGISTRY%type;
sql_query_stmt varchar2(120);
v_class STARSHIP.CLASS%type;
begin
Registry :='NCC1701';
sql_query_stmt := 'select STARSHIP.CLASS from STARSHIP where
STARSHIP.REGISTRY = '''||Registry||'''';
execute immediate (sql_query_stmt)into v_class ;
dbms_output.put_line(sql_query_stmt);
dbms_output.put_line(v_class);
end;

RefCursor
RefCursor is a built in type
You use it to build types for use in your code, not directly.
It is really a pointer to a cursor
It can be used to build dynamic sql that can handle multiple
return values

type refcur_t is ref cursor;
my_query varchar2(50) := 'Select TYPE.CLASS from TYPE';
my_class TYPE.CLASS%type;
curr1 refcur_t;
Using A Ref Cursor
Open the Cursor
While more rows
Fetch in a row
End While
Close Cursor

open curr1 for my_query;
loop
fetch curr1 into my_class;
exit when curr1%NOTFOUND;
end loop;
close curr1;

Nested Blocks
You can define a block, procedure or
function inside another.
These may only be called from inside the
function
They define a new namespace
Definitions of variables inside a block mask
those from outside
Nesting Example
procedure Resize (n1 NUMBER, n2 NUMBER) is
num1 NUMBER;
num2 NUMBER;
function Window (...) RETURN REAL IS
num1 VARCHAR2;
procedure Elapse (d1 DATE, d2 DATE) IS
num2 DATE
begin
...
end; Proc Elapse
begin
...
end Func Window
begin
...
End Proc Resizes;
Bulk Binds
PL-SQL is interpreted and run by one module of the
server process.
SQL in the code is run by another
Repetitive SQL causes context switches slowing
down the code.
Groups of SQL in PL-SQL can be bound together to
be done at once using the forall keyword.
bulk execute immediate statement can bulk bind
SQL that affects multiple rows
Bulk Bind Example
declare
type RegList is varray(3) of VARCHAR2;
ships RegList :=
RegList(NCC1701,NCC1701D,NCC1701E);
begin
Forall j in 2..3 -- bulk-bind only part of varray
update STARSHIP
set STARSHIP.LOCATION = Sector 12
where STARSHIP.REGISTRY = ships(j);
end;
Returning
A mechanism for getting info back into your
program after DML
Insert, Update and Delete can be modified by
the Returning clause
This returns column values from the affected
row into your program.
Works on one DML action at a time
Returning Example
Update PERSONEL set PERSONNEL.WAGES =
PERSONNEL.WAGES * 1.1
where PERSONNEL.ID = MS388 returning
PERSONNEL.NAME, PERSONNEL.WAGES
into V_Name, V_Sal;
Other Functions
Pipes
Allows named pipes to be used to pass information
between sessions active on same server
UTL_FILE
Allows PL/SQL code to read/write from OS level files
UTL_HTTP
Allows PL/SQL code to connect via HTTP protocols

Vous aimerez peut-être aussi