Академический Документы
Профессиональный Документы
Культура Документы
19
C H A P T E R
In This Chapter
Discovering knowledge at hand for the journey ahead Finding where this chapter fits in with your enterprise Using a simple library system as a case study Deciding when and how to use stored Procedures and functions Using Packages for business Object modeling Comprehending stored subprogram internals Using Triggers Handling errors proactively
nowing how to use stored subprograms is paramount in distributing business processes in any enterprise using Oracle8. This chapter will assist you in the evolution of implementing solutions using stored Procedures, functions, Packages, and Triggers.
462
are termed anonymous because they can only be executed when they are compiled and loaded into memory prior to a call from an application. Stored Procedures, functions, Packages, and Triggers within the Oracle world are also known as subprograms. You can express business- or database-related tasks through the use of logically grouped SQL and PL/SQL statements within these subprograms. You can also create subprograms strictly for local execution in tools that have the PL/SQL engine. For example, Oracle Forms and SQL*Plus can alternately be stored in the Oracle Data Dictionary, where they are available to other Users and applications connected to the Oracle database. Such subprograms are known as stored subprograms. The only difference between subprograms and stored subprograms is the latter requires a CREATE command to allow database residency. This chapter focuses on stored subprograms. Stored subprograms are stored in a Users Schema in a compiled database format known as pseudocode (p-code). In this method, when called, Oracle loads the Object into a shared pool in the System Global Area (SGA). Then the PL/SQL engine and SQL executors collaborate to process the statements within that Object. The following diagram, Figure 19-1, conceptually illustrates how a stored subprogram is executed from a client application.
463
Oracle server
PL/SQL engine
Program code
Program code
ra
ta ls
tem
Procedure B
Function B
Trigger C Package A
Oracle stored subprograms provide the capability to embrace all the preceding business Object requirements for the following reasons: 3 You can use the powerful PL/SQL language to custom-tailor your business needs. 3 Stored subprograms are Objects in their own right. Thus, you can break programs down into manageable well-defined logical modules that translate to Oracle stored subprograms. This process supports top-down design and the stepwise refinement approach to problem solving.
SQL
464
3 Once created and tested, stored subprograms can be used with confidence. You can usually make modifications to well-designed loosely coupled subprograms without affecting the rest of the component architecture. 3 To use stored subprograms, you must know what they do, not how they work. Therefore, you can design business applications without worrying about specific implementation details. The easiest way to understand stored Procedures and functions is to perceive them as their counterpart Procedures and functions in C, PowerBuilder, Delphi, or any other third- or fourth-generation language. Procedures and functions enable you to combine the ease and flexibility of SQL with the procedural functionality of a structured programming language through the use of PL/SQL. The major difference between an Oracle stored Procedure and an Oracle function is a function has to return a value. Packages, on the other hand, can be best understood as logically grouped Procedures and functions encapsulated together in a single unit. Here each exposed Procedure or function within a Package can be called independently. One important aspect of Oracle Procedures and functions residing in Packages is you can overload them.
Contains a list of all student and respective information. Contains a list of library books. Contains a list of books on loan to students. Contains a list of departments in which students may reside. Contains a list of books reserved by students. Contains a list of students that have book fines.
465
Stored Procedures
Stored Procedures can be instrumental in distributing business and data processing from your client application to the database server. The database server will almost certainly be a fault tolerant machine and possess more CPU power than the client machines. It possesses the capability to process most business tasks extremely quickly and securely. At the same time, it can reduce the network traffic between the client and the Oracle server. It makes good sense to use stored Procedures in most database-intensive applications. In most application development environments, which contain system architects, developers, and database administrators, the developers have to implement the application in their base programming language (PowerBuilder, C++, Delphi, or Visual Basic). Situations arise where embedded SQL over stored Procedures is used to implement a business- or data-related task. Such preferences result from the basic principles of not knowing how to construct a stored Procedure. Creating stored Procedures is not rocket science, but there is some effort required to understand them.This section focuses on the methodical process of creating, altering, and maintaining stored Procedures. To distribute your applications truly and efficiently, it is important to understand these concepts as combined with the power of PL/SQL and SQL.
466
loan_key INTEGER; reserve_key INTEGER; book_due DATE; book_wait INTEGER; reserved_loaned EXCEPTION; BEGIN /*Check if the book is on loan or reserved */ reserve_key := book_reserved(book_num); SELECT book_loan_id INTO loan_key FROM BOOKS WHERE book_id = book_num; IF loan_key > 0 OR reserve_key > 0 THEN IF loan_key > 0 THEN -- Get the due back date of the book SELECT bl_loan_date INTO book_due FROM BOOKS_LOANED WHERE bl_loan_id = loan_key; END IF; IF reserve_key > 0 THEN -- Get the wait list on the book SELECT reserved_wait_no INTO book_wait FROM BOOKS_RESERVED WHERE reserved_id = reserve_key; END IF; RAISE reserved_loaned; ELSE -- Book is available to be loaned INSERT INTO BOOKS_LOANED VALUES ( books_on_loan.nextval, book_num, student_num, SYSDATE, 0); COMMIT; UPDATE BOOKS SET book_loan_id = books_on_loan.currval WHERE book_id = book_num; COMMIT; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN loan_status := The book could not be found in the Library System.; WHEN reserved_loaned THEN IF loan_key > 0 THEN loan_status := The book is currently on loan and is due for return on || (book_due + 30) || .; END IF; IF reserve_key > 0 THEN Loan_status := loan_status || || The book is reserved with a waiting list of || book_wait || persons ; END IF; END;
467
Immediately the similarities will be obvious. The preceding example contains the CREATE command with parameter definitions, a variable declaration section, a Procedure body of PL/SQL and SQL expressions, and, importantly, an exceptionhanding section.
You can use SQL*Plus or the Oracle SQL Worksheet tools to create stored Procedures.
Specification section
CREATE [OR REPLACE] <Procedure_name>
The CREATE keyword used alone with a legal PL/SQL stored Procedure name initiates the creation of a stored Procedure. The Procedure name given to a stored Procedure uniquely identifies it within a single Schema. Any modifications to the Procedure after successful creation require you to drop the stored Procedure using the DROP PROCEDURE command each time. This type of creation is typical in production environments to avoid accidental modifications to stored Procedures, but can be extremely frustrating in development environments where modifications are quite common. To alleviate this frustration, use the CREATE OR REPLACE statement. With this statement, the stored Procedure is automatically dropped (if it already exists) and re-created.
Note
The CREATE OR REPLACE method of creating stored Procedures does not prompt you to drop the Procedure first.
[(argument [{IN | OUT | IN OUT}] Datatype
468
This component of the stored Procedure statement defines the arguments that can be passed in and out of the stored Procedure during execution. This argument list is optional, in which case the stored Procedure will return a success or failure return code.
Parameters types
In Oracle, two types of parameters are used within PL/SQL: formal and actual. Both stored Procedures and functions allow formal parameters to be defined within their respective specification sections. Actual parameters are arguments from a subprogram block, which feed the stored Procedure. In constrast, formal parameters are part of the stored Procedure declaration. For example, call the loan_book Procedure from the following anonymous block:
SET SERVEROUTPUT ON --Allow output to go to your screen / DECLARE msg VARCHAR2(200); student_id INTEGER := 1; book_id INTEGER := 1; BEGIN loan_book(student_id,book_id,msg); END;
The student_id, book_id, and msg variables are actual parameters as they feed their values into the preceding Procedure. Their presence only has meaning in the context of the subprogram block. Formal parameters are the container variables used exclusively within the stored Procedure to pass back their values to their respective actual parameters in the subprogram.
Note
You cannot impose the NOT NULL Constraint on a formal parameter. Also, use different names for actual and formal parameters, even if it involves adding a prefix to their names to differentiate them.
Parameters modes
Formal parameters have modes, which describe their behavior in the definition of a stored Procedure or a function. These modes are IN, OUT and IN OUT. 3 IN defines the formal parameter as an input variable to the stored subprogram. This type of formal parameter is read-only and cannot be assigned a value within the subprogram body. The actual parameter can be a Constant (for example, 135, Tony, or a variable). 3 OUT defines the formal parameter used as a container for returning a value to its respective actual parameter. You cannot use this type of parameter within expressions as they can only be assigned values within the subprogram body. This parameter must be a variable.
469
3 IN OUT defines the formal parameter as a container variable you can use both within expressions and assign values to return back to its respective actual parameter. This type of parameter must be a variable. The following loan_book Procedure provides an example:
CREATE OR REPLACE PROCEDURE loan_book( student_num IN INTEGER, book_num IN INTEGER, loan_status IN OUT VARCHAR2 )
The formal parameters student_num and book_num can be constants or variables. In either case, you cannot assign a value to them. You can use the formal parameter loan_status within expressions and assign it values.
Parameter datatypes
The datatype defines the legal PL/SQL datatype of a formal parameter. The difference between defining datatypes for actual and formal parameters is the formal datatypes cannot be constrained (for example, Varchar2(10) or Number(4)). Instead, you must use nonconstraining datatypes (for example, Varchar2 and Number). If there is a requirement to constrain the formal parameter, you can use %Type or %Rowtype attributes.The %Type attribute typecasts a formal parameter to a Column defined in a Table. For example, the student_id formal parameter in the loan_book Procedure could be typecast as the student_id Column in the Students Table.
student_num IN students.student_id%TYPE
Because of this attributes flexibility, an alteration of the underlying Columns does not necessitate a change of the formal parameters. The %RowType attribute creates a record that contains all the Columns in a specified Table. This attribute is mainly used to typecast OUT formal parameters where the values of a complete Table record are required. Lets assume the full details of a particular book in the library are required. Instead of declaring all the Columns of the BOOKS Table as formal parameters, you only need to specify the book%RowType formal parameter. The following example illustrates this strategy:
CREATE OR REPLACE PROCEDURE get_book_details (book_num IN books.book_id%TYPE, book_rec OUT books%ROWTYPE) ASBEGINSELECT BOOK_ID, BOOK_PUBLISHER, BOOK_AUTHOR_FIRST ,BOOK_AUTHOR_LAST,BOOK_TITLE, BOOK_SUBJECT ,BOOK_DEPT_ID
470
,BOOK_LOAN_ID book_num;END;
WHERE BOOK_ID =
To retrieve and display the book details, use the following subprogram:DECLARE BOOK_ROW BOOKS%ROWTYPE;BEGINGET_BOOK_DETAILS(1, BOOK_ROW); DBMS_OUTPUT.PUT(book_row.BOOK_ID || );DBMS_OUTPUT.PUT(book_row.BOOK_AUTHOR_FIRST || ); DBMS_OUTPUT.PUT(book_row.BOOK_AUTHOR_LAST || ); DBMS_OUTPUT.PUT(book_row.BOOK_TITLE || ); DBMS_OUTPUT.PUT(book_row.BOOK_SUBJECT || ); DBMS_OUTPUT.PUT(book_row.BOOK_DEPT_ID || ); DBMS_OUTPUT.PUT(book_row.BOOK_LOAN_ID || ); DBMS_OUTPUT.NEW_LINE; END;
Note
Important: the underlying Tables and Columns should exist before using these attributes. Also, the SELECT INTO statement must exactly match the Columns in the Table.
DEFAULT parameters
If there is a requirement to allow IN formal parameters to be initialized to a value, defaults can be implemented by the following conventions: 1. Specifying the keyword DEFAULT in the formal parameter definition:
e.g. student_num IN Students.student_id%TYPE DEFAULT 134;
You cannot dynamically bind default values to their formal parameters upon execution. For example:
student_id IN Students.student_id%TYPE DEFAULT :student_id;
Defaults allowing a subprogram to be called without specifying their DEFAULT IN actual values as the defaults will automatically be used within the subprogram. The only Constraint in using defaults is the actual parameter list in executing the subprogram must be positional or notationally correct.
471
The actual parameters are passed in the same order as their counterpart formal parameters are defined. Named Notation. The named method of passing actual parameters involves specifying the formal parameter and the actual value assigned to it. These specifications enable you to pass parameters in any order to the Procedure. The following loan_book Procedure could be called with the following syntax:
loan_book(loan_status=>msg,book_num=>book_id,student_num=> student_id);
The Procedure body usually contains an error handling section called the EXCEPTION. This section is executed whenever an error is raised or occurs based on a predefined PL/SQL error group. Declared exceptions either trap execution error or constrain business conditions and execute the appropriately defined error handling code. This chapter details exceptions in a following section.
472
Compiled state
Stored Procedures are executed in a compiled format, which greatly reduces code execution times.
Memory residence
Upon execution, stored Procedures reside in an Oracle shared memory pool. This strategy reduces disk I/O compared to loading it on every call. Only a single copy of a stored Procedure is required in memory.
Functions
Functions are similar to stored Procedures except they are required to return a value. Here is an easy way to differentiate between stored Procedures and functions: stored Procedures perform an action while functions compute a value. Using functions in the same manner as a stored Procedure is a poor standard and a semantic issue for developing a system. For example, the loan_book Procedure could easily be defined as a function. With Table updating and insertion occurring, however, this Procedure is not a logical candidate for an Oracle function.
Chapter 19 3 Functions
473
For example, the following function returns a single value indicating the total loan fines accrued for a student:
CREATE OR REPLACE FUNCTION student_fines (student_num IN INTEGER) RETURN REAL AS book_fine REAL; total_fine REAL := 0; CURSOR scroll_fines (student_key INTEGER) IS SELECT bl_fine FROM BOOKS_LOANED WHERE bl_student_id = student_key; BEGIN Update_book_fines(student_num); OPEN scroll_fines(student_num); LOOP FETCH scroll_fines INTO book_fine; EXIT WHEN scroll_fines%NOTFOUND; total_fine := total_fine + book_fine; END LOOP; CLOSE scroll_fines; UPDATE students_fines SET sf_fine = total_fine WHERE sf_student_id = student_num; RETURN total_fine; END;
Function components
As with stored Procedures, functions are divided into two parts: the specification and the function body. The function body is analogous to an anonymous subprogram block in which the function is actually coded using PL/SQL and SQL expressions.
Specification section
CREATE [OR REPLACE] FUNCTION Function_name [(argument [{IN | OUT | IN OUT}] Datatype [{:= | DEFAULT} expression]
The CREATE OR REPLACE command replaces and creates the function specified by the function name. The CREATE FUNCTION command only creates the function requiring an existing function be dropped first by the DROP FUNCTION command. As with the stored Procedure, the inclusion of a functions parameter list is optional.
RETURN return_Datatype
474
Use the RETURN statement to pass a return value back to the caller of the function. This value is usually used as part of a callers expression. A function can have more than one RETURN statement in its function body, but only one RETURN statement is used. (Multiple exit points in a function is poor programming practice.)
Note
In stored Procedures, a RETURN statement cannot contain an expression it simply returns control to the caller before you reach the normal end of the Procedure.
Packages
A Package is a group of anonymous PL/SQL Objects, Procedures, and functions encapsulated into one logical unit. Therefore, the complete specification of certain business processes can be encapsulated into one Object. This encapsulation creates a true business Object with many interfaces, each one handling a specific business task. Like stored Procedures and functions, a Package consists of two distinct parts: the specification and the body. There is, however, a distinct difference in how Packages are created.
Chapter 19 3 Packages
475
Package body
CREATE OR REPLACE PACKAGE BODY library_management AS PRAGMA SERIALLY_REUSABLE; FUNCTION book_reserved (book_num IN INTEGER) RETURN INTEGER AS wait_no INTEGER := 0; BEGIN SELECT MAX(reserved_wait_no) INTO wait_no FROM books_reserved WHERE reserved_book_id = book_num; RETURN wait_no; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN wait_no; END book_reserved; PROCEDURE loan_book(student_num IN INTEGER, book_num IN INTEGER, loan_status IN OUT VARCHAR2 ) AS loan_key INTEGER; reserve_key INTEGER; book_due DATE; book_wait INTEGER; reserved_loaned EXCEPTION; BEGIN /*Check if the book is on loan or reserved */ reserve_key := book_reserved(book_num); SELECT book_loan_id INTO loan_key FROM BOOKS WHERE book_id = book_num; IF loan_key > 0 OR reserve_key > 0 THEN IF loan_key > 0 THEN -- Get the due back date of the book SELECT bl_loan_date INTO book_due FROM BOOKS_LOANED WHERE bl_loan_id = loan_key; END IF; IF reserve_key > 0 THEN -- Get the wait list on the book SELECT reserved_wait_no INTO book_wait FROM BOOKS_RESERVED WHERE reserved_id = reserve_key; END IF; RAISE reserved_loaned; ELSE -- Book is available to be loaned INSERT INTO BOOKS_LOANED VALUES ( books_on_loan.nextval, book_num, student_num, SYSDATE, 0);
(continued)
476
Chapter 19 3 Packages
477
BEGIN Update_book_fines(student_num); OPEN scroll_fines(student_num); LOOP FETCH scroll_fines INTO book_fine; EXIT WHEN scroll_fines%NOTFOUND; total_fine := total_fine + book_fine; END LOOP; CLOSE scroll_fines; dbms_output.put_line(TO_CHAR(total_fine)); UPDATE students_fines SET sf_fine = total_fine WHERE sf_student_id = student_num; RETURN total_fine; END student_fines; PROCEDURE return_book( student_num IN INTEGER, book_num IN INTEGER, book_status OUT INTEGER, fine_info OUT VARCHAR2) AS loan_key INTEGER; student_fine REAL := 0; BEGIN -- Get the loan information SELECT book_loan_id INTO loan_key FROM books WHERE book_id = book_num; -- Get the fines due for the student student_fine := student_fines(student_num); -- Update the BOOKS table UPDATE books SET book_loan_id = 0 WHERE book_id = book_num; -- Delete the loan Record DELETE books_loaned WHERE bl_loan_id = loan_key; COMMIT; book_status := 1; fine_info := The student has a remaining fine of $ || student_fine; END return_book; END library_management;
Package components
Package specification
The specification, also known as the Package header, only contains the public definitions of its contents. The specification defines the Packages interface to the calling applications and Users.
478
The name of a Package must be unique in a given Schema and both the Package specification and body must share the same name. The Package specification Objects can use similar names if Object overloading is required. (I discuss overloading in a following section.) Any defined Public Objects must be declared first. If Procedure A calls Procedure B, Procedure B must be defined in the Package specification before Procedure A. PL/SQL Objects declared in the Package specification are global they can be called or used by external Users who have EXECUTE privilege for the Package or have EXECUTE ANY PACKAGE privileges.
Note
The arguments defined for each Package specification Object must match those defined in the Package body for their respective Object declarations.
Package initialization
Following the declaration of the public and private subprograms in the Package body, an initialization section can be defined. You can use this section to initialize Package variables. You cannot pass parameters to the initialization section here and you only run it once when you execute the package for the first time.
Chapter 19 3 Packages
479
Executing Packages
When you call a Package, you actually reference one of its interfaces. To reference a Package interface, use dot notation. For example, use the following syntax to call the reserve_book Procedure within the library_management.
Package:DECLARE Student_id NUMBER := 1; Book_id NUMBER := 43; BEGIN EXECUTE library_management.reserve_book(student_id, book_id) END;
480
7. Process retention. Packaged public Objects persist in memory for the life of a session, so they can be shared by all executing subprograms in that session. Also, these Objects data is retained across transactions without having it stored in the database.
The datatypes must be in a different family, as an INTEGER datatype is in the same family as REAL datatype. Heres an example:
CREATE OR REPLACE PACKAGE overload_example AS FUNCTION Insert_Loan_Date (book_id IN INTEGER, loan_date IN DATE ); FUNCTION Insert_Loan_Date (book_id IN INTEGER, loan_date IN VARCHAR2 ); END overload_example.
Chapter 19 3 Packages
481
A serially reusable Package has a state for the one call to the Package then its memory is deallocated and its state is destroyed. All variables initialized and set by the Package are lost. The memory allocated for serially reusable Packages is kept in a small global pool not in the UGA. This memory is used for one logical unit of work and then released back to the pool to be reused by different Users. This facility enables developers to design and deploy applications with improved scaleability and memory efficiency. To mark a Package as serially reusable, use the following PRAGMA:
PRAGMA SERIALLY_RESUABLE;
For example, if you marked the library_system Package as serially reusable, you must add the preceding PRAGMA to the specification and body section as follows:
CREATE OR REPLACE PACKAGE library_management AS PROCEDURE loan_book(student_num IN INTEGER, book_num IN INTEGER, loan_status IN OUT VARCHAR2 ) ; PROCEDURE reserve_book (student_num IN INTEGER,book_num IN INTEGER); PROCEDURE return_book(student_num IN INTEGER,book_num IN INTEGER,book_status OUT INTEGER,fine_info OUT VARCHAR2); PRAGMA SERIALLY_REUSABLE; END library_management;
Dropping Packages
The DROP PACKAGE drops the specification and the body parts of a defined Package.The Package must exist in your Schema or you must have the DROP ANY PACKAGE privilege.
Note
To drop just one construct, you have to remove it from the Package and then recompile the Package.
Oracle-supplied Packages
Oracle 8 provides built-in Packages that enable the application developer to take advantage of predefined functionality. You can treat these Packages as foundation Objects. For example, the Package UTL_HTTP allows PL/SQL to communicate with the Internet and retrieve Web pages if required. (This is a very useful Package for managing intranets and extranets.) The following Packages extend the power of PL/SQL and SQL:
482
DBMS_SESSION DBMS_TRANSACTION DBMS_SQL DBMS_UTILITY DBMS_STANDARD DBMS_OUTPUT DBMS_DDLS DBMS_ALERT UTL_HTTP UTL_FILE
CrossReference
Please refer to the Oracle reference manual for the complete syntactical usage and descriptions of these built-in Packages.
Subprogram Internals
This section enhances your knowledge about stored subprograms, which include stored Procedures, functions, and Packages.
483
The system privilege required by the subprogram has been revoked from PUBLIC or the stored subprogram owner. Required Object privileges for Objects referenced by the subprogram have been revoked from PUBLIC or the stored subprogram owner.
Status recording is a recursive process. For example, a Package may reference a Procedure that in turn references a view that also has dependencies brought on by underlying Tables. To check if a stored subprogram is valid, view it in the Oracle Schema Manager or use the following SQL:
SELECT Object_name, Object_type, status FROM USER_OBJECTS WHERE Object_name = LOAN_BOOK
484
Caution
Oracle is case sensitive to the Object names! Oracle validates Object dependencies by using the timestamp or signatures dependency models.
Timestamp model
Timestamps are set for an Object whenever the Oracle server recompiles or creates them. Figure 19-2 examines the dependency of a Package and a stored Procedure that access a Table.
Oracle package
Table D
Figure 19-2: A Package and a stored Procedure that access a Table have dependencies.
If Procedure C is altered, the subprograms, Procedure A and function B within the Package, are immediately marked invalid if they are on the same server as Procedure C. The compiled states of Package A contain records of the timestamp of Procedure C. If Procedure C is altered and recompiled, its timestamp no longer matches the value recorded during the initial compilation of the Package. If Procedure C was on a different node than the Package, Procedure C is marked invalid at runtime when a call takes place from the Package. Package A would then need to be recompiled. The disadvantage of using the timestamp model is the unnecessary recompilation of dependent Objects across the network.
485
Signature model
To resolve the timestamp models problems of remote dependencies, Oracle provides additional capabilities using the signature model. The signature model only affects remote dependencies. The timestamp model does not affect local Objects. Recompilation is always possible. In the signature model, a subprogram contains the following attributes: 3 Name of subprogram 3 Base types of the parameters 3 Modes of the parameters Only modifications to the last two signature attributes are significant to affect a signature match. A signature is associated with each compiled PL/SQL Object and identifies the Object using the following criteria: 3 Name of the Object 3 Datatype of each parameter 3 Modes of the parameters 3 Number of parameters 3 The type of return value of a function
Dependency notes
3 If you change the default value in a stored subprogram, you still get the old value until the subprogram is recompiled.
486
3 If you add a new overloaded Procedure in a Package, local Procedures that call the remote Procedure are not invalidated. The Package has to recompile so that rebinding takes place for the new overloaded function to be executed. 3 In the timestamp model, if the timestamp does not match the timestamp of the called Procedure, the calling (dependent) object is invalidated and must be recompiled. If there is no local PL/SQL compiler, the calling application cannot proceed. 3 Using the signatures model, the timestamps are compared first. If they do not match, the signatures are compared. If they do not match, an error is returned to the calling application. 3 Server-side Users can use either timestamp or signature models, but if the application is distributed, the signature model avoids recompilations. 3 Client-side PL/SQL Users should set the parameter to signature. This setting enables installation of new applications at client sites without recompiling. 3 When using the signature model, add new Procedures to the end of a Package specification declaration. Otherwise, recompilation is necessary.
Dependency implementation
The User controls which dependency model to use timestamp or signature.
Note
The timestamp model is the default implemented by Oracle. If you use the signature model, you need to adjust the
REMOTE_DEPENDENCIES_MODE parameter in the init.ora file.
Syntax:
REMOTE_DEPENDENCIES_MODE=SIGNATURE|TIMESTAMP
487
The input_file is the fully qualified name of the wrapper input file. The output_file is optional because the output PL/SQL binary has the same name as the input file (except with a .plb extension).
CrossReference
Example:
SHOW ERRORS PROCEDURE loan_book;
You can also use the following views to list errors with varying levels of scope: 3 USER_ERRORS 3 ALL_ERRORS 3 DBA_ERRORS To list general information about stored subprograms, use these views to view the subprogram source and other Object attributes: 3 ALL_SOURCE 3 USER_SOURCE 3 DBA_SOURCE 3 USER_OBJECT_SIZE 3 DBA_OBJECT_SIZE
488
Triggers
Triggers are similar to stored subprograms except in the following ways: 3 Triggers are implicitly executed when a Table is modified regardless of User or applications acting on the Table. 3 Triggers are defined only for database Tables. 3 Triggers do not accept arguments. 3 A Trigger can only be executed or fired by issuing the following DML actions on a Table: Update, Insert, and Delete. Triggers are paramount in the development of production data-oriented systems because they perform the following tasks: 3 Prevent invalid data transactions 3 Implement complex security 3 Enforce Referential Integrity (RI) across nodes in a distributed database 3 Create strategic and complex business rules 3 Provide transparent logging 3 Provide auditing 3 Maintain synchronous Tables 3 Gather statistics on frequently modified Tables
Note
Because Triggers can be implicitly invoked, do not introduce recursion Triggers calling other Triggers when implementing.
Chapter 19 3 Triggers
489
Triggers also enforce RI across different nodes of a distributed database. You can use complex rules for RI that involve Triggers to control of flow statements (that is, IF.. THEN or CASE Statements).
Trigger syntax
Triggers are actually made up of three distinct parts: statement, restriction, and action. The following syntax creates a Trigger:
CREATE [OR REPLACE ] TRIGGER <TRIGGER_NAME> {BEFORE|AFTER} [INSTEAD OF] TRIGGERING EVENT ON <TABLE_NAME> [FOR EACH ROW [WHEN TRIGGERING RESTRICTION]] <TRIGGER BODY>
Trigger components
A Trigger is made up of three components:
Statement
CREATE [OR REPLACE ] TRIGGER <TRIGGER_NAME> {BEFORE|AFTER} [INSTEAD OF] TRIGGERING EVENT ON <TABLE_NAME>
490
As with other stored subprograms, you can add the REPLACE keyword to the CREATE statement to drop and re-create the Trigger automatically without having to use the DROP command. The Trigger name must be a legal unique PL/SQL name in the Users Schema for Triggers. The name can be the same name as other Objects that are not Triggers, but this naming scheme causes confusion in the development and maintenance phase of any project. The timing of a Trigger, whether the Trigger is executed before or after the Triggering statement, is implemented by the BEFORE or AFTER options. The AFTER option is more efficient than the BEFORE option because affected data blocks must be logically read once for the Trigger and then for the Triggering statement. The AFTER option requires the data block to be read only once for the Trigger and the Trigger statement.
Note
The Triggering event is the SQL statement that causes the Trigger to fire, regardless of whether the Trigger is an UPDATE, DELETE, or INSERT.
BEFORE Triggers can be instrumental in deciding whether you should permit a
statement to complete. This can eliminate unnecessary processing and rollback if an exception is raised. You can also derive Column values before completing an INSERT or UPDATE operation on a Table.
AFTER Triggers validate the UPDATE, INSERT, and DELETE operations after they have taken place and allow rollback on exceptions raised.
Trigger timing permits four types of Triggers: 3 AFTER row 3 AFTER statement 3 BEFORE row 3 BEFORE statement Each Statement can either be for an UPDATE, INSERT, or DELETE operation, allowing twelve combinations of Trigger types that can be defined on one Table.
Note
If the Triggering event is an update, you can specify a Column list that needs to be modified. Because INSERT and DELETE operations affect entire rows, Column lists cannot be defined in those cases.
Chapter 19 3 Triggers
491
IF Inserting then... END IF; IF Updating then... END IF; IF Deleting... END IF;
492
CREATE OR REPLACE TRIGGER Update_student_loan_status BEFORE INSERT OR UPDATE ON STUDENTS_FINES FOR EACH ROW WHEN (NEW.SF_STUDENT_ID < 100 )
Trigger execution
A Trigger can be executed in two modes: enabled or disabled. The enabled Trigger is executed if the restriction is true, but the disabled Trigger is not executed even if restriction is true. (By default Triggers are enabled when first created.)
Chapter 19 3 Triggers
493
For enabled Triggers, Oracle executes Triggers of the same type in a planned firing order when more than one Trigger is executed by a Triggering statement. Each subsequent Trigger sees changes made by the previous Triggers. Each Trigger also sees the old and new values. The old values are the original values and the new values are the current values. You may want to disable a Trigger if its referencing Object is unavailable or a large data load is to be performed. To disable a Trigger, use the following statement:
ALTER TRIGGER Trigger_name DISABLE;
To re-enable disabled Triggers, use the preceding command replacing the DISABLE with ENABLE.
ALTER TRIGGER Trigger_name ENABLE;
Note
To enable or disable the Triggers, you must have ALTER Schema Object privileges for the Table or have ALTER ANY TABLE system privileges.
494
In this execution model, all actions and checks must succeed. If an exception is raised within a Trigger and the exception is not explicitly handled, all actions performed by the fired Triggers are rolled back. This execution model takes into account the integrity Constraints and disallows Triggers that violate declarative integrity Constraints.
Note
Triggers of different types fire in a particular order, but Triggers of the same type for the same firing statement are not guaranteed to fire in specific order. Do not design applications based on prerequisite Trigger processing. Although any Trigger can execute a sequence of operations via inline or by calling Procedures, using multiple Triggers of the same type enhances database administration by permitting modular installation of applications that have Triggers on the same Tables. To ensure multiple Triggered actions occur in a specific order, you must consolidate these actions by calling Procedures within a single Trigger.
Mutating Tables
A mutating Table is a Table in the state of modification by an UPDATE, DELETE, or INSERT statement. A Table can also be updating from the effects of a declarative DELETE CASCADE referential Constraint. A constraining Table is a Table that a Triggering statement may need to read directly, via SQL statements, or indirectly for declarative referential integrity Constraints. (A Table is mutating or constraining only to the session that issued the Statement in progress.)
Note
Tables are never considered mutating or constraining for statement Triggers, unless the Trigger fires as a result of a DELETE CASCADE.
Chapter 19 3 Triggers
495
For all row or statement Triggers executed for a DELETE CASCADE, there are two restrictions regarding mutating and constraining Tables. These restrictions prevent a Trigger from viewing erroneous data because: 1. The SQL statements of a Trigger cannot read from a query or modify a mutating Table of the Triggering statement. 2. The statements of a Trigger cannot change the Primary, Foreign, or Unique Key Columns of a constraining Table of the Triggering statement.
Note
There is an exception to this restriction. If BEFORE row and AFTER row Triggers are fired by a single row insert to a Table, do not treat that Table as mutating or constraining.
Modifying a Trigger
Like a stored Procedure, you cannot explicitly alter a Trigger. You must replace a Trigger with a new definition. You use the ALTER TRIGGER command only to recompile, enable, and disable a Trigger. When replacing a Trigger, you must include the OR REPLACE in the CREATE TRIGGER statement. Alternately, you can drop the Trigger using the DROP TRIGGER command and issue the CREATE TRIGGER statement again.
496
Compiling Triggers
Triggers are similar to PL/SQL blocks with the addition of the :new and :old qualifiers, but their compilation is different. Compilation involves three stages: 1. Syntax checking. 2. Semantic checking. 3. Code generation. Triggers are fully compiled when the CREATE TRIGGER command is issued and the p-code is stored in the Data Dictionary. If errors occur during the compilation, the Trigger is still created, but all instructions to execute the Trigger fail. View the errors with the SHOW ERRORS command or SELECT the error from the USERS_ERROR view. To manually recompile a Trigger, use the ALTER TRIGGER command:
ALTER Trigger Trigger_name COMPILE;
Debugging Triggers
You can use the same debugging facilities as with other subprograms.
497
Internal errors are Oracle errors returned to a PL/SQL block during execution or are caused by certain operations within the PL/SQL code (for example, divide by zero or an out-of-memory scenario). User-defined errors are explicitly defined by the developer and signaled within the PL/SQL block to control processing of errors specific to the application. When an error occurs within a stored subprogram, the following processes take place: 1. An exception is raised. 2. Normal execution of the stored subprogram stops. 3. Control transfers to the exception-handling section of the PL/SQL block. You can write specific exception handlers to handle internal or User-defined errors. 4. Control is passed back to the caller of the stored subprogram. Any variables passed by reference are not changed and all modifications are rolled back to the last COMMIT or SAVEPOINT commands.
Implementing exceptions
Internal exceptions are raised implicitly by the runtime system you do not have a choice in the matter. Oracle dictates the raising of an exception. User-defined errors, on the other hand, must be raised explicitly by the RAISE statement. By defining your own exceptions, you can also raise predefined exceptions provided by Oracle (for example, NO_DATA_FOUND). You should define User-defined exceptions in the declarative part of a PL/SQL block. Unlike internal exceptions, you must give them a name. Usually the naming scheme follows a business rule exception you want to capture, such as the reserved_loaned exception used in the stored Procedure loan_book. To handle raised exceptions, you have to code separate routines called exception handlers that process the exception according to your specific business requirements. After an exception handler runs, the current block stops executing and the enclosing block resumes with the next statement. If there is no enclosing block, control returns to the host environment.
498
effect. Also, your code becomes littered with repeated error checks after every command. For example:
BEGIN Select.. Check for errors Select.. Check for errors Select.. Check for errors End;
With exceptions, you can handle errors conveniently without coding multiple error checks. Exceptions also improve readability by isolating error-handling routines from the normal business logic. An example follows:
BEGIN Select.. Select.. EXCEPTION WHEN NO_DATA_FOUND THEN END;
Handling exceptions
To handle errors in your stored subprograms, you have to implement exceptionhandling routines that manage both your business-specific exceptions and Oracles internal errors.
Internal errors
As stated previously, an internal exception is raised implicitly whenever PL/SQL violates an Oracle rule or exceeds a system-dependent rule. Because every Oracle error has a number and exceptions have to be handled by name within PL/SQL, Oracle provides predefined internal exceptions. For example, the Oracle exception NO_DATA_FOUND is raised when a SELECT INTO statement returns no rows. Use the OTHERS handler to handle other errors. The error reporting functions SQLCODE and SQLERRM are especially useful in the OTHERS handler because they return the Oracle error code and message. For a complete list of predefined Oracle errors, see the Oracle reference manual.
499
After an exception is raised, control passes to the exception section of the subprogram. To direct exceptions to their respective exception control block, you must use the following structure in your code to process the error:
EXCEPTION WHEN EXCEPTION 1 THEN Sequence of Statements; WHEN EXCEPTION 2 THEN Sequence of Statements; WHEN EXCEPTION 3 THEN Sequence of Statements; WHEN OTHERS THEN
The optional OTHERS is always the last handler in a block or subprogram; there can be only one OTHERS exception. I discuss the OTHERS option later on in this chapter. If you are required to handle different exceptions with the same exception handling block, use Boolean operator OR. For example:
EXCEPTION WHEN EXCEPTION1 or EXCEPTION2.
Note
Exception scope
As a rule, you cannot declare an exception twice in the same block. Exceptions declared in a block are considered local to that block and global to all its subblocks. Because a block only references local or global exceptions, enclosing blocks cannot reference the exceptions declared in subblocks.
500
In this syntax, the exception name is the declared exception. The following example illustrates its usage:
-- Declarative section. Deadlocked_detected EXCEPTION PRAGMA EXCEPTION_INIT(Deadlocked_detected, -60) BEGIN EXCEPTION WHEN Deadlocked_detected THEN --handle the error code END;
In this syntax, the error number is a negative number in the range -20,000 to -20,999 and the message is a character string up to 2048 bytes long. If the optional third parameter of TRUE is used, the error is placed on the stack of previous errors. If FALSE is used, the current error replaces all previous errors on the error stack.
Summary
Today, function-rich and thin application clients that are easily maintainable and lean in terms of resource utilization are needed. This process is known as tiering. Two- and three-tier applications are moving the data processing and complex business processes away from the application client into the realms of central and database server architectures. Oracle8 provides four schema objects that facilitate the migration of the data-centric processing from the application client and into the umbrella of the Oracle8 Server. These Oracle8 schema objects are: stored Procedures, functions, Packages, and Triggers.
Chapter 19 3 Heading 1
501
From a development point, each of these Schema objects are extensible, modular, reusable, and maintainable. The richness of the Oracle8 PL/SQL language allows these Schema objects to be coded in a fashion similar to objects created in 3GL and 4GL languages. This flexibility in the code allows the Schema objects to be custom-tailored exactly to their role on the Oracle8 database server. The following key points summarize this chapter: 3 Stored Procedures and functions can be used extensively to perform complex data processing with the enhanced PL/SQL extensions to the SQL language. Although they reside in the database, stored Procedures and functions permit the creation of methods similar to those found in 3GL and 4GL languages. 3 Packages can be used to capture the behavior of a real-world Object through the encapsulation of all of its methods. Packages can be viewed as providing the interfaces to the data Object, which is the Table in the relational world. 3 Triggers, enhanced through the PL/SQL language, provide a powerful means of enforcing Constraints and complex rules on the data inserted and modified in an Oracle8 Table.