Slide - Temple CIS

Chapter 15
How to create
stored procedures
and functions
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 1
Objectives
Applied
 Create stored procedures and user-defined functions using any of the
features presented in this chapter.
 Code CALL statements and scripts that call stored procedures.
 Code SQL statements that use user-defined functions.
 Create a package of stored procedures and functions.
 Use Oracle SQL Developer to work with procedures, functions, and
packages.
 Use Oracle SQL Developer’s debugger to debug a procedure or
function.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 2
Objectives (continued)
Knowledge
 Explain why a stored procedure executes faster than an equivalent SQL
script.
 Describe the difference between passing parameters by position and
passing them by name.
 Describe the basic process for validating data within a stored procedure
or function.
 Describe the benefits of using packages for stored procedures and
functions.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 3
Procedural Extensions and Stored Procedures
• SQL provides a module language
– Permits definition of procedures in SQL, with if-thenelse statements, for and while loops, etc.
• Stored Procedures
– Can store procedures in the database
– then execute them using the call statement
– permit external applications to operate on the database
without knowing about internal details
Functions and Procedures
• SQL:1999 supports functions and procedures
– Functions/procedures can be written in SQL itself, or in an external
programming language.
– Functions are particularly useful with specialized data types such as
images and geometric objects.
• Example: functions to check if polygons overlap, or to compare
images for similarity.
– Some database systems support table-valued functions, which can
return a relation as a result.
• SQL:1999 also supports a rich set of imperative constructs,
including
– Loops, if-then-else, assignment
• Many databases have proprietary procedural extensions to SQL
that differ from SQL:1999.
The CREATE PROCEDURE statement
CREATE [OR REPLACE] PROCEDURE procedure_name
[(
parameter_name_1 data_type
[, parameter_name_2 data_type]...
)]
{IS | AS}
pl_sql_block
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 6
A stored procedure that updates a table
CREATE OR REPLACE PROCEDURE update_invoices_credit_total
(
invoice_number_param VARCHAR2,
credit_total_param
NUMBER
)
AS
BEGIN
UPDATE invoices
SET credit_total = credit_total_param
WHERE invoice_number = invoice_number_param;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 7
A statement that calls the stored procedure
CALL update_invoices_credit_total('367447', 300);
A script that calls the stored procedure
BEGIN
update_invoices_credit_total('367447', 300);
END;
/
A script that passes parameters by name
BEGIN
update_invoices_credit_total(
credit_total_param=>300,
invoice_number_param=>'367447');
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 8
The syntax for declaring parameters
parameter_name_1 [IN|OUT|IN OUT] data_type
A stored procedure that uses parameters
CREATE OR REPLACE PROCEDURE update_invoices_credit_total
(
invoice_number_param IN VARCHAR2,
credit_total_param
IN NUMBER,
update_count
OUT INTEGER
)
AS
BEGIN
UPDATE invoices
SET credit_total = credit_total_param
WHERE invoice_number = invoice_number_param;
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 9
The stored procedure (continued)
SELECT COUNT(*)
INTO update_count
FROM invoices
WHERE invoice_number = invoice_number_param;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
SELECT 0 INTO update_count FROM dual;
ROLLBACK;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 10
A script that calls the stored procedure
SET SERVEROUTPUT ON;
DECLARE
row_count INTEGER;
BEGIN
update_invoices_credit_total('367447', 200, row_count);
DBMS_OUTPUT.PUT_LINE('row_count: ' || row_count);
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 11
The syntax for declaring an optional parameter
parameter_name_1 data_type [DEFAULT default_value]
A statement that uses an optional parameter
CREATE OR REPLACE PROCEDURE update_invoices_credit_total
(
invoice_number_param VARCHAR2,
credit_total_param
NUMBER
DEFAULT 100
)
AS
BEGIN
UPDATE invoices
SET credit_total = credit_total_param
WHERE invoice_number = invoice_number_param;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 12
A statement that calls the stored procedure
CALL update_invoices_credit_total('367447', 200);
Another statement that calls the stored procedure
CALL update_invoices_credit_total('367447');
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 13
The syntax of the RAISE statement
RAISE exception_name
A procedure that raises a predefined exception
CREATE OR REPLACE PROCEDURE update_invoices_credit_total
(
invoice_number_param VARCHAR2,
credit_total_param
NUMBER
)
AS
BEGIN
IF credit_total_param < 0 THEN
RAISE VALUE_ERROR;
END IF;
UPDATE invoices
SET credit_total = credit_total_param
WHERE invoice_number = invoice_number_param;
COMMIT;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 14
A statement that calls the procedure
CALL update_invoices_credit_total('367447', -100);
The response from the system
Error report:
SQL Error: ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "AP.UPDATE_INVOICES_CREDIT_TOTAL", line 9
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 15
A script that calls the procedure
SET SERVEROUTPUT ON;
BEGIN
update_invoices_credit_total('367447', -100);
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('A VALUE_ERROR occurred.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'An unknown exception occurred.');
END;
/
The response from the system
A VALUE_ERROR occurred.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 16
The RAISE_APPLICATION_ERROR procedure
RAISE_APPLICATION_ERROR(error_number, error_message);
A statement that raises an application error
RAISE_APPLICATION_ERROR(-20001,
'Credit total may not be negative.');
The response if the error isn’t caught
Error report:
SQL Error: ORA-20001: Credit total may not be negative.
ORA-06512: at "AP.UPDATE_INVOICES_CREDIT_TOTAL", line 10
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 17
A script that catches an application error
BEGIN
update_invoices_credit_total('367447', -100);
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('A VALUE_ERROR occurred.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'An unknown exception occurred.');
END;
/
The response from the system
An unknown exception occurred.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 18
A stored procedure that validates data
CREATE OR REPLACE PROCEDURE insert_invoice
(
vendor_id_param
invoices.vendor_id%TYPE,
invoice_number_param
invoices.invoice_number%TYPE,
invoice_date_param
invoices.invoice_date%TYPE,
invoice_total_param
invoices.invoice_total%TYPE,
payment_total_param
invoices.payment_total%TYPE
DEFAULT 0,
credit_total_param
invoices.credit_total%TYPE
DEFAULT 0,
terms_id_param
invoices.terms_id%TYPE
DEFAULT NULL,
invoice_due_date_param invoices.invoice_due_date%TYPE
DEFAULT NULL,
payment_date_param
invoices.payment_date%TYPE
DEFAULT NULL
)
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 19
A stored procedure that validates data (continued)
AS
invoice_id_var
terms_id_var
invoice_due_date_var
terms_due_days_var
BEGIN
IF invoice_total_param
RAISE VALUE_ERROR;
END IF;
invoices.invoice_id%TYPE;
invoices.terms_id%TYPE;
invoices.invoice_date%TYPE;
INTEGER;
< 0 THEN
SELECT invoice_id_seq.NEXTVAL INTO invoice_id_var
FROM dual;
IF terms_id_param IS NULL THEN
SELECT default_terms_id INTO terms_id_var
FROM vendors WHERE vendor_id = vendor_id_param;
ELSE
terms_id_var := terms_id_param;
END IF;
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 20
A stored procedure that validates data (continued)
IF invoice_due_date_param IS NULL THEN
SELECT terms_due_days INTO terms_due_days_var
FROM terms WHERE terms_id = terms_id_var;
invoice_due_date_var :=
invoice_date_param + terms_due_days_var;
ELSE
invoice_due_date_var := invoice_due_date_param;
END IF;
INSERT INTO invoices
VALUES (invoice_id_var, vendor_id_param,
invoice_number_param, invoice_date_param,
invoice_total_param, payment_total_param,
credit_total_param, terms_id_var,
invoice_due_date_var, payment_date_param);
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 21
Three statements that call the stored procedure
CALL insert_invoice(34, 'ZXA-080', '30-AUG-08', 14092.59,
0, 0, 3, '30-SEP-08', NULL);
CALL insert_invoice(34, 'ZXA-080', '30-AUG-08', 14092.59,
0, 0, 3, '30-SEP-08');
CALL insert_invoice(34, 'ZXA-080', '30-AUG-08',
14092.59);
The response for a successful insert
CALL insert_invoice(34, succeeded.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 22
A statement that raises an error
CALL insert_invoice(34, 'ZXA-080', '30-AUG-08',
-14092.59);
The response when a validation error occurs
Error report:
SQL Error: ORA-06502: PL/SQL: numeric or value error
ORA-06512: at "AP.INSERT_INVOICE", line 20
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 23
A stored procedure that drops a table
CREATE OR REPLACE PROCEDURE drop_table
(
table_name VARCHAR2
)
AS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
/
A statement that calls the stored procedure
CALL drop_table('test1');
The response from the system
CALL drop_table('test1') succeeded.
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 24
The syntax of the DROP PROCEDURE statement
DROP PROCEDURE procedure_name
A statement that creates a stored procedure
CREATE PROCEDURE clear_invoices_credit_total
(
invoice_number_param VARCHAR2
)
AS
BEGIN
UPDATE invoices
SET credit_total = 0
WHERE invoice_number = invoice_number_param;
COMMIT;
END;
/
A statement that drops a stored procedure
DROP PROCEDURE clear_invoices_credit_total
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 25
The syntax for creating a function
CREATE [OR REPLACE] FUNCTION function_name
[(
parameter_name_1 data_type
[, parameter_name_2 data_type]...
)]
RETURN data_type
{IS | AS}
pl_sql_block
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 26
A function that returns a vendor ID
CREATE OR REPLACE FUNCTION get_vendor_id
(
vendor_name_param VARCHAR2
)
RETURN NUMBER
AS
vendor_id_var NUMBER;
BEGIN
SELECT vendor_id
INTO vendor_id_var
FROM vendors
WHERE vendor_name = vendor_name_param;
RETURN vendor_id_var;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 27
A SELECT statement that uses the function
SELECT invoice_number, invoice_total
FROM invoices
WHERE vendor_id = get_vendor_id('IBM')
The response from the system
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 28
A function that calculates balance due
CREATE OR REPLACE FUNCTION get_balance_due
(
invoice_id_param NUMBER
)
RETURN NUMBER
AS
balance_due_var NUMBER;
BEGIN
SELECT invoice_total - payment_total - credit_total
AS balance_due
INTO balance_due_var
FROM invoices
WHERE invoice_id = invoice_id_param;
RETURN balance_due_var;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 29
A statement that calls the function
SELECT vendor_id, invoice_number,
get_balance_due(invoice_id) AS balance_due
FROM invoices
WHERE vendor_id = 37;
The response from the system
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 30
A statement that creates a function
CREATE FUNCTION get_sum_balance_due
(
vendor_id_param NUMBER
)
RETURN NUMBER
AS
sum_balance_due_var NUMBER;
BEGIN
SELECT SUM(get_balance_due(invoice_id))
AS sum_balance_due
INTO sum_balance_due_var
FROM invoices
WHERE vendor_id = vendor_id_param;
RETURN sum_balance_due_var;
END;
/
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 31
A statement that calls the function
SELECT vendor_id, invoice_number,
get_balance_due(invoice_id) AS balance_due,
get_sum_balance_due(vendor_id) AS sum_balance_due
FROM invoices
WHERE vendor_id = 37;
The response from the system
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 32
The syntax of the DROP FUNCTION statement
DROP FUNCTION function_name
A statement that drops a function
DROP FUNCTION get_sum_balance_due;
Murach’s Oracle SQL and
PL/SQL, C15
© 2014, Mike Murach & Associates, Inc.
Slide 33