Sie sind auf Seite 1von 41

UNIT1

To examine how a stored PL/SQL package can enhance application development and
performance
explain the concept of a PL/SQL package and identify the advantages of using
such a package
describe how a PL/SQL package is created and how packaged objects are executed
explain how a PL/SQL composite datatype can be stored in a package and passed
as a parameter to a packaged procedure or function
explain how Oracle supports the overloading of PL/SQL subprogram names
explain how Oracle uses the standard package to define the PL/SQL environment
PL/SQL objects can be encapsulated into a single stored program unit called a
PL/SQL package.
A PL/SQL package can contain both functions and procedures.
In fact, a package can contain any of these PL/SQL objects:
function
procedure
constant
variable
cursor
exception
A PL/SQL package can enhance Oracle application development in a number of
ways:
enhanced modularity
information hiding
persistent data
improved performance
A PL/SQL package enhances program modularity by encapsulating related
procedures, functions, and other objects into a single named PL/SQL package.
You can think of a PL/SQL package as a "library" of functional objects.
For example, a package can contain all the objects needed to process student
information.
Or a package can contain all the objects needed to process student loans.
A package allows information hiding by specifying objects as public or private.
A public package object can be executed by any calling program.

But a private package object is known only within the scope of the defining
package.
Information hiding allows easier application maintenance because a package can be
changed without changing the application programs that use the package, provided
the interface remains the same.
Public package variables and cursors are retained for the duration of the session
and can be referenced by any application.
This is called persistent data.
A PL/SQL package can improve application performance.
When a package object is first called, the entire package is loaded into memory.
And any application can call any object in the package without needing disk I/O to
reload the package into system memory.
A PL/SQL package is not a subprogram.
A package cannot be "executed".
It cannot be passed parameters and it cannot return a value.
But the individual objects within a PL/SQL package can be called or executed by
front-end application tools.
In addition to creating and using your own PL/SQL packages, you can use the
objects contained in pre-defined packages supplied by Oracle.
Packages can significantly improve the speed and quality of application
development.
But package design, creation, and maintenance must be carried out in a structured
manner.
And it is particularly important that packages are properly documented and tested.
The DBA should ensure that proper procedures are established and followed.
Like a procedure or function, a PL/SQL package is declared in two parts:
specification

body
Here is the basic syntax for a package specification.

The CREATE PACKAGE keywords are used to create the package specification.
And the "owning" schema is specified along with the package name:
schema.package_name
Multiple public objects such as functions and procedures can be declared.
A user can call a public packaged object provided he or she has EXECUTE privilege
on the package.
Here is the basic syntax for a package body.

The keywords CREATE PACKAGE BODY are used.


And you must use the same schema and package name that was used in the
package specification.

A package body consists of the executable code for packaged objects.


Public and private objects are coded in the same way in the package body.
But an object coded in the package body is public if it is declared in the package
specification.
An application developer must have CREATE PROCEDURE privilege on the database
to create a public package.
Your DBA can grant the necessary privilege.
Let's look at an example package called enroll_new.
Here is the package specification.

The package is named enroll_new and is owned by the admission schema.


Two public procedures are declared: charge_stu and grade_new.
A package specification is created separately from the package body by using a
script file or by entering the code interactively at the SQL> prompt.
You can examine package source code and syntax errors by querying the
user_source and user_error views of the owning schema.
Here is the code for the example package body.

Two procedures are coded.


And because both procedures were declared in the package specification, they are
public package objects.
When the script containing the package body is created, the packaged procedures
admission.enroll_new.charge_stu and admission.enroll_new.grade_new can be called
by any application tool in the Oracle environment.
Dot notation must be used to access a packaged object:
schema_name.package_name.object_name
This is how a packaged object is executed at the SQL> prompt.

This is how a packaged object is called from within a PL/SQL block or subprogram.

The keyword EXECUTE is not required to execute a subprogram from within a


PL/SQL block.
A user must have EXECUTE privilege on a package in order to successfully execute
an application program that calls a packaged object.

But the user does not need table level privileges because the privileges of the
package owner are granted implicitly for the duration of the execution of the called
object.
Application development can be standardized and modularized by declaring
composite datatypes as public objects in a PL/SQL package.
You can code a TYPE declaration for a user-defined RECORD or TABLE datatype as a
public packaged object.
And then declare instances of that datatype in multiple application programs
throughout the Oracle environment.
You don't need to code a TYPE declaration in each application that uses the
packaged datatype.
Developers can create a "library" package of datatype declarations that can be
reused in any application.
A PL/SQL package can be changed without recompiling the applications that use the
package's objects.
Here is an example package specification that declares two user-defined datatypes
as public packaged objects.

A package body is not needed because all the package contents are datatypes.
Once the package has been created and stored in the database, instances of the
user-defined datatypes can be declared in any application.
Here is an example PL/SQL block that declares an instance of the student_record
datatype.

It is not necessary to recode a TYPE declaration in the calling program.


Oracle will obtain the TYPE declaration for the user-defined datatype app_record
from the packaged object appdev.records.student_record.

The owning schema of the packaged object is appdev.


The package name is records.
And the packaged object name is student_record.
You can pass an instance of a user-defined RECORD or TABLE datatype into a
packaged subprogram as an actual parameter.
For example, in a calling program you can declare an instance of a user-defined
RECORD datatype by calling a packed object that contains the TYPE declaration.
And then populate and pass the RECORD fields into another packaged procedure as
actual parameters.
The called packaged procedure appdev.maintain can also declare an instance of the
user-defined RECORD by calling the appdev.records package.
The important point to remember is that you can use a package to contain a data
structure declaration.
And you can reuse that data structure anywhere in the Oracle environment without
having to recode the declaration.
You can pass an instance of a user-defined RECORD or TABLE datatype into a
packaged subprogram as an actual parameter.
For example, in a calling program you can declare an instance of a user-defined
RECORD datatype by calling a packed object that contains the TYPE declaration.

And then populate and pass the RECORD fields into another packaged procedure as
actual parameters.

The called packaged procedure appdev.maintain can also declare an instance of the
user-defined RECORD by calling the appdev.records package.
The important point to remember is that you can use a package to contain a data
structure declaration.
And you can reuse that data structure anywhere in the Oracle environment without
having to recode the declaration.
Oracle allows the same subprogram name to be used for more than one PL/SQL
packaged subprogram, provided the formal parameters are different.
This concept is called overloading.
Overloading can be used to allow a single call to access multiple functions and
procedures.
For example, a PL/SQL package can contain a procedure that accepts a VARCHAR2
formal parameter.
And the same package can contain a second procedure of the same name that
accepts a NUMBER formal parameter.
Oracle resolves overloading by comparing the actual parameters supplied at runtime with the formal parameters declared in the packaged subprograms.
Here is an example package that contains two procedures called del_stu.

If del_stu is called and has passed a VARCHAR2 parameter, the first procedure will
execute.

And if del_stu is passed a NUMBER parameter, the second procedure will execute.
Overloading works only if the formal parameters in each subprogram differ in
number, order, or datatype.
Subtypes of datatype NUMBER are not considered different for the purpose of
overloading subprogram names.
Oracle7 uses a package called standard to define the PL/SQL environment.
The standard package declares datatypes, exceptions, functions, and procedures.
All declarations in the standard package are public and are globally visible to all
applications and users.
This means that any object declared in the standard package is available to any tool
in the Oracle environment that supports PL/SQL.
For example, the no_data_found exception is declared in the standard package.
And it can be used by any PL/SQL program.

SQL*Plus functions such as TO_NUMBER and DECODE are also declared in the
standard package.
The standard package is created by the DBA by running a script file called
standard.sql.
The script that creates the standard package is usually stored in the
\oracle\rdbms\admin directory.
Once it is created, the standard package is stored in parsed format in the database.
The standard package is like any other stored PL/SQL package.
When a user calls a packaged object, the package is loaded and held "resident" in
memory.
Another user can use an object in the package without causing disk I/O.
Here is an extract from the script used to create the standard package.

Be careful not to declare a function or procedure with the same name as an object
in the standard package.

If you do, the local declaration will override the global declaration and the core
functionality of PL/SQL may be affected.
A number of other packages are also supplied with Oracle7.
These packages contain procedures and functions that can assist the efficient
development and administration of the database.
The dbms_output package is particularly useful in debugging applications.
For example, you can output variable values to screen.

The package dbms_output is created by executing the script dbmsopt.sql.

UNIT 2
You will now develop a sample PL/SQL package and calling program.
Here is the specification for the sample package and calling program.

To begin, let's examine what the package and calling program should do logically.
The package should contain a public function that accepts a RECORD datatype as a
formal parameter and inserts a new row in the student table.
And the function should return a value to the calling program to indicate whether a
row was successfully inserted.
The package should also contain a public procedure that accepts a social security
number as a parameter and deletes a row from the student table.

And finally, the calling program should call and pass parameters to the packaged
function to create a new student.
That's what the program should do logically.
The next step is to code the package specification.
The specification should declare the function and procedure as public packaged
objects.
Remember, a calling program has access only to public packaged objects declared
in the package specification.
To begin the specification, a CREATE statement should be coded.
Next, a RECORD datatype is declared to hold the student details.

It is not necessary to declare an instance of this RECORD in the package


specification.
Once the package is created, instances can be declared by any calling PL/SQL
program.
Next, the function to create a student is declared.
The CREATE keyword is not needed within the package.
An instance of the RECORD datatype should be declared as a formal parameter in
the function.
The RETURN clause specifies that a NUMBER datatype is returned to the calling
program.

Finally, the procedure to delete a student is declared.

A formal IN parameter is specified in the procedure declaration.


That's the end of the package specification.
The script is executed to create and store the package specification in the database.
The next step is to code the package body to contain the executable code for the
packaged function and procedure.
First, the CREATE statement should be coded.
Next, the function specification is coded.

And the function body is coded.

Next, the procedure specification is coded.

And finally, the procedure body is coded.


That's the end of the package body.

The next step is to code the calling program.


First, an instance of the packaged datatype is declared.

Dot notation is used to reference the packaged object.


Statements are coded to prompt the user to enter run-time values.

Next, an IF statement should be coded to call the function and pass in the actual
parameters.
That's the end of the calling program.

Let's examine what happens when the calling program is executed.


First, a data structure called local_record is created in memory using the TYPE
declaration contained in the packaged object appdev.students.student_row.
Next, the user is prompted to populate local_record with run-time values.
The packaged function appdev.students.input_rec is called and passed local_record
as an actual parameter.
The calling program is temporarily suspended.
And Oracle begins executing the public packaged function
appdev.students.input_rec.
First, the actual parameter local_record is accepted into the formal parameter
student_record.
The parameter student_record is an instance of the user-defined datatype
student_row.
student_row was declared as a public packaged object in the package specification.
Next, the INSERT statement creates a new row in the base table student.
If the insert is successful, the RETURN statement returns a value of 1 to the calling
program.
If the update failed for any reason, the exception handler returns a value of 0 to the
calling program.
The packaged function finishes executing when the return statement is executed.

But the package is still resident in memory.


And any user can call any object in the package without causing disk I/O.
The calling program resumes executing and evaluates the return value received
from the packaged function.
And a suitable message is output to screen.

Here is the run-time output generated if the insert was carried out successfully.
Look at how PL/SQL substitutes the run-time values entered by the user for the
declared substitution variables.

This sort of feedback can be useful in debugging an application.


But end-users should always be "shielded" from unfriendly messages by using frontend application development tools such as Developer/2000 Forms.
Interface design is examined in detail in the CBT Systems course Developer/2000
Forms: Fundamentals.

PL/SQL supports a stored program unit called a database trigger.


This is stored as a PL/SQL procedure in the database and is associated with a named
database table.
A database trigger cannot be associated with a view.
A database trigger is like a stored function or procedure.
It consists of PL/SQL and SQL*Plus code.
It can call and pass parameters to a packaged PL/SQL procedure or function.
However, it cannot be called or executed by a user or application program.
A database trigger is independent of users and applications.
A database trigger is executed or fired automatically by Oracle when predefined
SQL*Plus DML (data manipulation language) statements are executed on the
associated base table.
This means that a trigger can fire only when one or more of these DML statements
are executed:
INSERT
UPDATE
DELETE
A database trigger cannot fire when a SELECT statement is executed.
A database trigger should not be confused with a Developer/2000 Forms trigger. The
role of a trigger in the Developer/2000 Forms environment is examined in the CBT
Systems course Developer/2000 Forms: Fundamentals.
Database triggers can help protect the integrity of the database in several ways.
A database trigger can carry out complex validation to enforce business rules.
For example, it can fire to prevent an application from inserting data that does not
meet predefined criteria.
A database trigger can be used to carry out event logging.
For example, in a transaction processing environment, it can insert data about DML
operations in an event log table.
A database trigger can help the DBA to control DML operations.

For example, it can fire to prevent a user or application from updating base table
data outside authorized times.
A database trigger has three parts:
event
restriction
body
A trigger event specifies the table name and the DML statement(s) that cause a
database trigger to fire.
For example, you can specify an INSERT statement on the student table as a trigger
event.
And when that event occurs, the trigger will fire.
A single trigger can have multiple trigger events.
But a trigger's events can only specify a single table.
A trigger restriction is an optional boolean PL/SQL expression that can be used only
with a particular type of database trigger called a ROW trigger.
It is evaluated to determine whether to continue firing a trigger.
A restriction can be omitted, in which case the trigger will be fired every time the
trigger event occurs.
A trigger body contains the executable statements that are carried out when the
trigger is fired.
A trigger body is like any PL/SQL block.
It can have a declare section, a procedure section, and an exception section.
A database trigger is created and stored using the CREATE TRIGGER statement.
Here is the basic syntax required to create a database trigger.

You must be granted the appropriate privilege by the DBA to successfully create a
database trigger.
The privilege CREATE TRIGGER allows you to create a trigger in your schema.
And CREATE ANY TRIGGER allows you to create a trigger in another schema.
A user or application does not require privileges on a database trigger or on any
tables accessed by a trigger.
The privileges of the schema that "owns" the trigger are implicitly granted for the
duration of the execution of the trigger.
A trigger can fire before or after a DML operation.
A BEFORE trigger is fired before the triggering DML statement is executed.
So, it can be used to determine whether to abort the triggering statement.
It can also be used to derive values before an INSERT or UPDATE statement is
executed.
An AFTER trigger is fired after the triggering DML statement has executed.
It can be used to enforce integrity constraints or log DML activity.
A trigger can fire on INSERT, UPDATE, or DELETE statements.
And a trigger can fire at ROW level or at STATEMENT level.
In all, there are twelve possible triggering events for each table.

So, you can create a maximum of twelve triggers on any table.


In releases of Oracle prior to 7.1, you cannot create more than one trigger type per
table.
Here is the basic algorithm that Oracle uses when firing stored database triggers.

A database trigger is a fail-safe mechanism to protect data integrity.


A trigger is not a substitution for proper table definition or adequate security and
data validation techniques.
Referential integrity constraints should continue to be included in the CREATE TABLE
statement.
In fact, a trigger cannot override constraints or change data in a constraining table
referenced in the triggering statement.
A table is constrained if it defines a foreign key relationship with another table.

Security and data validation should be implemented in the front-end application


before base table data manipulation is attempted.
An exception raised in a trigger should be handled at trigger level by coding an
exception section in the trigger body.
An unhandled exception will cause a complete rollback of the triggering statement.
Because database triggers cause a performance overhead, they should be used
with discretion.
It is the responsibility of the DBA to develop a comprehensive strategy for the
enforcement of data integrity rules.
And it is the responsibility of application developers to ensure that programs are
"trigger-aware".
A database trigger has some limitations.
A database trigger cannot issue a SELECT statement to a table that is mutating.
A base table that is in the process of changing is said to be mutating.
For example, a trigger that is in the process of firing cannot read from the table it is
firing on.
Although you can use SQL*Plus DML statements in a trigger, you cannot use DDL or
DCL statements.
For example, statements such as CREATE TABLE and GRANT SELECT are not
supported in a database trigger.
And you cannot use Oracle's transaction processing options: COMMIT, ROLLBACK,
and SAVEPOINT.
Oracle supports a STATEMENT database trigger that fires once when a triggering
DML statement is executed.
A STATEMENT trigger can be specified to fire before or after an INSERT, UPDATE, or
DELETE statement.
Here is an example BEFORE INSERT STATEMENT trigger.

STATEMENT is the default trigger type.


A CREATE TRIGGER statement is used to create and name the STATEMENT trigger.
The trigger will fire when the event "BEFORE INSERT ON student" occurs.
A trigger restriction cannot be coded in a STATEMENT trigger.
The IF statement in the example trigger body tests whether Oracle's internal date
SYSDATE is greater than 'JAN-1-95'.
And if it is, the trigger is forced to fail and the triggering DML statement is aborted.
The example trigger code is saved as a script and executed at the SQL> prompt to
create and store the trigger in the database.
Here is the feedback generated when the example STATEMENT trigger is caused to
fire by an INSERT statement on the student table.

Here is an example of an AFTER DELETE STATEMENT trigger.

A CREATE TRIGGER statement is used to create and name the trigger.


This example STATEMENT trigger will fire when the event "after delete on student"
occurs.
When the example trigger is fired, it inserts a row in the event_log table.
Now look at this SQL statement.

The DELETE statement causes an "after delete on student" event.


And the trigger fires, inserting a row into the event_log table.
The user is unaware that the trigger has fired.
Remember, a trigger is independent of users and applications.
A SELECT statement on the event_log table verifies that the trigger fired
successfully.

In general, an AFTER trigger makes better use of memory and causes less
performance overhead than a BEFORE trigger.
Oracle supports a ROW database trigger.
Like a STATEMENT trigger, a ROW trigger can be created to fire before or after a
DML statement.
And a ROW trigger event can be specified to fire on UPDATE, INSERT, or DELETE.
But a ROW trigger fires once for each row affected by a triggering statement, while
a STATEMENT trigger fires just once.
Here is an example of an AFTER DELETE ROW trigger that fires when the event
"after delete on student" occurs.

The keywords FOR EACH ROW specify that the trigger fires for each row affected by
the triggering event.
Remember, Oracle creates a STATEMENT trigger by default if the keywords FOR
EACH ROW are omitted.
The trigger body IF statement will insert a row in the debts_outstanding table after
each row is deleted, provided the deleted loan_amount is greater than zero.
Look again at the IF statement condition in the example ROW trigger.
This code uses a notation called a correlation name.
It can be used in a ROW trigger to reference a data element that is in the process of
mutating.
In this case, the correlation name OLD references data in a row that has just been
logically deleted by the triggering statement.
And loan_amount references the base table column in the "deleted" row.
A correlation name is preceded by a colon (:), unless it is used in a trigger
restriction.
You can reference a deleted row in a trigger using the correlation name OLD
because the deletion has not yet been committed to the database.
Think about what happens at run-time.
This statement causes all the rows in the student table to be deleted.

And after each row is deleted, the example trigger fires once.
If the value of :OLD.loan_amount in the logically deleted row is greater than zero,
the trigger inserts a row in the debts_outstanding table.
In an INSERT ROW trigger there is no old value, but you can use the NEW correlation
name to refer to an inserted data element: :NEW.column_name
In an UPDATE ROW trigger you can use both the OLD and NEW correlation names to
compare data values before and after the update, for example IF
(:OLD.column_name > :NEW.column_name) THEN...
In a DELETE ROW trigger, there is no new value, so only the OLD correlation name
can be used.
Oracle does not support correlation names in a STATEMENT trigger.
Oracle allows the default correlation names to be renamed using this syntax in the
ROW trigger event: REFERENCING [NEW | OLD] AS REFERENCE_NAME
Here is an example of a trigger that uses referencing to "rename" the correlation
names OLD and NEW.

This technique can be used to avoid potential naming conflicts.


A trigger restriction can be used in a ROW trigger to determine whether to execute
the trigger body for each row affected by the triggering statement.
Here is the syntax for a ROW trigger restriction.

The trigger condition can be any valid boolean PL/SQL expression, but cannot
include a query.
Look now at this example AFTER UPDATE ROW trigger that uses a restriction.

A colon is not used with a correlation name in a ROW trigger restriction.


The trigger restriction is evaluated for each row affected by the DML statement.
If the restriction evaluates to TRUE, the trigger body is executed and a row is
inserted in the refer_debt_collector table.
And if the restriction evaluates to FALSE, the next row is considered.
A STATEMENT trigger does not support restriction.
Look again at the example trigger event.

The loan_amount column in the student table has been specified in the trigger
event.
This means that the trigger will fire only if data in that column is affected by an
UPDATE statement.
You can specify more than one base table column in an UPDATE trigger event.
If you omit a column reference, the trigger will fire when any column in the table is
affected by a triggering DML statement.

Oracle allows the use of the following conditional predicates in a STATEMENT or


ROW trigger that has more than one triggering event:
IF INSERTING THEN...
IF UPDATING THEN...
IF DELETING THEN...
This means that you can use a different set of trigger body statements for each
trigger event.
This is the basic syntax used in a trigger body to identify the triggering event and
execute the related statements.

Predicates can be combined: IF (INSERTING OR UPDATING) THEN...


Here is an example trigger that uses conditional predicates to determine which set
of trigger body statements should be executed.

The trigger event specifies that the trigger will fire before an INSERT, UPDATE, or
DELETE statement is executed on the student table.

The conditional predicates are used to identify the triggering event.


When the trigger is caused to fire by an INSERT or UPDATE statement, the first set of
statements are executed.
The function INITCAP is used to ensure that student names are inserted into the
base table in the correct case.
When the trigger is caused to fire by a DELETE statement, a row is inserted in the
student_archive table.
You can also use the conditional predicate to identify whether a specific base table
column has been affected by a triggering DML statement.

Database performance can be affected by the extra processing overhead generated


by a database trigger.
Performance can be a particular problem if a trigger is complex or if a large amount
of data is loaded at once.
In fact, it may be expedient to temporarily disable a database trigger before
carrying out bulk loading of data.
The Oracle utility SQL*Loader can be used to bulk-load data.
You can disable all triggers on a table.

Or you can disable an individual trigger.

If you decide to disable a base table trigger for the duration of a data load, it is
important that another method is used to validate the data.
The DBA only should decide whether a trigger should be disabled.
Triggers on a table can be re-enabled using the ENABLE keyword.

And a trigger can also be re-enabled individually.

You can delete a trigger from the database using this syntax: DROP TRIGGER
trigger_name;
When a trigger is created, the source code is stored in the database.
You can examine source code and other trigger details by querying these default
views:
user_triggers
dba_triggers
all_triggers
Here is the data definition of the user_triggers view.

This SELECT statement retrieves information on the triggers in the active schema.

The DBA can examine details of any trigger by using the views dba_triggers and
all_triggers.
UNIT 4
You will now develop a sample database trigger.
The trigger should insert a row in the grade_trans_log table whenever a row is
deleted from the grade table.
The purpose of this trigger is to maintain a transaction log.
The sample trigger should be created on the grade table.
The most appropriate trigger to use here is an AFTER DELETE ROW trigger.
An AFTER trigger is generally more efficient than a BEFORE trigger because a single
database call is generated.
A ROW trigger is generally more useful than a STATEMENT trigger because it can fire
once for each row affected by the triggering statement.

The first step in creating the sample trigger is to name the trigger grade_trigger.

Next, a trigger event should be coded.


The trigger will fire when the event "after delete on grade" occurs.

The trigger should fire once after each row is deleted.


The keywords FOR EACH ROW specify that the trigger is a ROW trigger that will fire
once after each row is deleted.
The next step in coding the sample trigger is the trigger body.
An INSERT statement is coded to create a new row in the grade_trans_log table after
each deletion from the grade table.

Correlation names should be used in the VALUES clause of the INSERT statement to
reference each row as it is deleted from the grade table.
The correlation name OLD refers to the row that has just been logically deleted by
the triggering statement.

The trigger is now completed.

The trigger code can be saved as a script and executed at the SQL> prompt to
create and store the trigger in the database.
This SQL statement causes four rows to be deleted from the grade table.

The triggering statement deletes four rows and causes the trigger event "after
delete on grade".
So the trigger is fired four times, once for each row affected by the triggering
statement.
A SELECT statement on the grade_trans_log table verifies that the trigger fired
successfully.

Das könnte Ihnen auch gefallen