2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
EXECUTE IMMEDIATE
user_objects
Trapping Exceptions
Composite Data Types
PL/SQL records:
PL/SQL collections:
INDEX BY Tables or Associative Arrays
Nested Tables
VARRAY
Parameter Passing
Overloading Subprograms
Using Forward Declarations
autonomous transactions
Returning Clause
Bulk Binding (FOR ALL) Bulk Collect
Triggers
Note:When you create any object such as table, procedure, function, and so on, the entries are made to the
user_objects table. When the code in the slide is executed successfully, you can check the user_objects
table by issuing the following command:
SELECT object_name,object_type FROM user_objects;
Note:You can use the DESCRIBE command to check the arguments and return type of the function. Example:
DESCRIBE check_sal;
Guidelines for Trapping Exceptions
Begin the exception-handling section of the block with the EXCEPTION keyword.
Define several exception handlers, each with its own set of actions, for the block.
When an exception occurs, PL/SQL processes only one handler before leaving the block.
Place the OTHERS clause after all other exception-handling clauses.
You can have only one OTHERS clause.
Exceptions cannot appear in assignment statements or SQL statements.
Trapping Non-Predefined Oracle Server Errors
Non-predefined exceptions are similar to predefined exceptions; however, they are not defined as PL/SQL
exceptions in the Oracle server. They are standard Oracle errors. You can create exceptions with standard Oracle
errors using the PRAGMA EXCEPTION_INIT function. Such exceptions are called non-predefined exceptions.
You can trap a non-predefined Oracle server error by declaring it first. The declared exception is raised implicitly. In
PL/SQL, the PRAGMA EXCEPTION_INIT tells the compiler to associate an exception name with an Oracle error
number. That allows you to refer to any internal exception by name and to write a specific handler for it.
Note: PRAGMA(also called pseudo instructions) is the keyword that signifies that the statement is a compiler
directive, which is not processed when the PL/SQL block is executed. Rather, it directs the PL/SQL compiler to
interpret all occurrences of the exception name within the block as the associated Oracle server error number
Note:Use the RAISE statement by itself within an exception handler to re-raise the same
exception and propagate it back to the calling environment.
Nested Tables
The functionality of nested tables is similar to INDEX BY tables; however, there
are differences in the nested table implementation. The nested table is a valid
data type in a schema-level table but an INDEX BY table is not. The key type for
nested tables is not PLS_INTEGER. The key cannot be a negative value unlike in
the INDEX BY table. Though we are referring to the first column as key, there is
no key in case of nested tables. There is a column with numbers in sequence which
is considered as the key column. Elements can be deleted from anywhere in a
nested table leaving a sparse table with non sequential keys. The rows of a
nested table are not in any particular order. When you retrieve values from a
nested table, the rows are given consecutive subscripts starting from 1. Nested
tables can be stored in the database unlike INDEX BY tables.
Syntax:
TYPEtype_nameISTABLEOF
{column_type|variable%TYPE
| table.column%TYPE} [NOT NULL]
| table.%ROWTYPE
In Oracle Database 10g, nested tables can be compared for equality. You can check
if an
element exists in the nested table and also if the nested table is a subset of
another.
If you do not initialize an INDEX BY table, then it is empty. If you do not initialize a nested
table, then it is automatically initialized to NULL. You can initialize the offices nested table
by using a constructor as shown below:
offices := location_type('Bombay', 'Tokyo','Singapore', 'Oxford');
Complete example:
SET SERVER OUTPUT ON DECLARE TYPE
location_type IS TABLE OF locations.city%TYPE;
offices location_type;
table_count NUMBER;BEGINoffices := location_type('Bombay',
'Tokyo','Singapore','Oxford');
table_count := offices.count();
FOR i in 1..table_count LOOP
DBMS_OUTPUT.PUT_LINE(offices(i));
END LOOP;
END;
VARRAY
Variable-size arrays (VARRAY)are similar to PL/SQL tables except that a VARRAY is constrained in size. VARRAY
is valid in a schema-level table. Items of VARRAY type are called VARRAYS. VARRAYS have a fixed upper
bound. You have to specify the upper bound when you are declaring them. This is similar to arrays in the C language.
The maximum size of a VARRAY is 2 gigabytes (GB) as in nested tables. The distinction between nested table and
VARRAY is the physical storage mode. The elements of a VARRAY are stored contiguously in memory and not in
the database. One can create a VARRAY type in the database by using SQL.
Example:
TYPE location_type IS VARRAY(3) OF locations.city%TYPE;
offices location_type;
The size of a VARRAY is restricted to 3. You can initialize a VARRAY by using constructors. If you try to initialize
the VARRAY with more than three elements, then a Subscript outside of limit error message is displayed.
Note: You cannot assign default values to OUT and IN OUT parameters.
Overloading Subprograms
The overloading feature in PL/SQL enables you to develop two or more packaged subprograms with the same name.
Overloading is useful when you want a subprogram to accept similar sets of parameters that have different data
types. For example, the TO_CHAR function has more than one way to be called, enabling you to convert a number
or a date to a character string.PL/SQL allows overloading of package subprogram names and object type methods.
The key rule is that you can use the same name for different subprograms as long as their formal parameters differ in
number, order, or data type family.
Consider using overloading when:
Processing rules for two or more subprograms are similar, but the type or number of parameters used varies
Providing alternative ways for finding different data with varying search criteria. For example, you may want to
find employees by their employee ID and also provide a way to find employees by their last name. The logic is
intrinsically the same, but the parameters or search criteria differ.
Extending functionality when you do not want to replace existing code
Note:
Restrictions
You cannot overload:
Two subprograms if their formal parameters differ only in data type and the different data types are in the same
family (NUMBER and DECIMAL belong to the same family.)
Two subprograms if their formal parameters differ only in subtype and the different subtypes are based on types in
the same family (VARCHAR and STRING are PL/SQL subtypes of VARCHAR2.)
Two functions that differ only in return type, even if the types are in different families You get a run-time error
when you overload subprograms with the preceding features
Since Oracle8i, the autonomous transactions were added to make it possible to create an independent transaction. An
autonomous transaction (AT) is an independent transaction started by another main transaction (MT). The slide
depicts the behavior of an AT:
1.The main transaction begins.
2.A proc2procedure is called to start the autonomous transaction.
3.The main transaction is suspended.
4.The autonomous transactional operation begins.
5.The autonomous transaction ends with a commit or roll back operation.
6.The main transaction is resumed.
The INSERT, UPDATE, and DELETE statements can include a RETURNING clause, which returns
column values from the affected row into PL/SQL variables or host variables. This eliminates
the need to SELECT the row after an INSERT or UPDATE, or before a DELETE.
To manage exceptions and have the bulk bind complete despite errors, add the SAVE EXCEPTIONS keyword to
your FORALL statement after the bounds, before the DML statement. Use the new cursor attribute
%BULK_EXCEPTIONS, which stores a collection of records with two fields:
%BULK_EXCEPTIONS(i).ERROR_INDEX holds the "iteration" of the statement during which the exception
was raised.
%BULK_EXCEPTIONS(i).ERROR_CODE holds the corresponding error code.
Values stored in %BULK_EXCEPTIONS refer to the most recently executed FORALL statement. Its subscripts
range from 1 to %BULK_EXCEPTIONS.COUNT.
FORALL: Example (continued)
An Additional Cursor Attribute for DML Operations
Another cursor attribute added to support bulk operations is %BULK_ROWCOUNT. The %BULK_ROWCOUNT
attribute is a composite structure designed for use with the FORALL statement. This attribute acts like an
index-by table. Its ith element stores the number of rows processed by the ith execution of an UPDATE or
DELETE statement. If the ith execution affects no rows, then %BULK_ROWCOUNT(i)returns zero.
For example:
CREATE TABLE num_table (n NUMBER);
DECLARE
TYPE NumList IS TABLE OF NUMBERINDEX BY BINARY_INTEGER;
nums NumList;
BEGIN
nums(1) := 1;
nums(2) := 3;
nums(3) := 5;
nums(4) := 7;
nums(5) := 11;
FORALL i IN nums.FIRST .. nums.LAST
INSERT INTO num_table (n) VALUES (nums(i));
You can combine several triggering events into one by taking advantage of the special conditional predicates
INSERTING, UPDATING, and DELETING within the trigger body.
Example
Create one trigger to restrict all data manipulation events on the EMPLOYEES table to certain business hours,
Monday through Friday.
INSTEAD OF Triggers
Use INSTEAD OF triggers to modify data in which the DML statement has been issued against an inherently
nonupdatable view. These triggers are called INSTEAD OF triggers because, unlike other triggers, the Oracle
server fires the trigger instead of executing the triggering statement. This trigger is used to perform an INSERT,
UPDATE, or DELETE operation directly on the underlying tables. You can write INSERT, UPDATE, or DELETE
statements against a view, and the INSTEADOF trigger works invisibly in the background to make the right actions
take place. A view cannot be modified by normal DML statements if the view query contains set operators, group
functions, clauses such as GROUP BY, CONNECT BY, START, the DISTINCT operator, or joins. For example, if a
view consists of more than one table, an insert to the view may entail an insertion into one table and an update to
another. So, you write an INSTEADOF trigger that fires when you write an insert against the view. Instead of the
original insertion, the trigger body executes, which results in an insertion of data into one table and an update to
another table.
Note: If a view is inherently updatable and has INSTEADOF triggers, then the triggers take precedence.
INSTEADOF triggers are row triggers. The CHECK option for views is not enforced when insertions or updates to
the view are performed by using INSTEADOF triggers. The INSTEADOF trigger body must enforce the check.
END IF;
END;
/
Triggers are fully compiled when the CREATE TRIGGER command is issued and the executable code is stored in
the data dictionary.
Note:If errors occur during the compilation of a trigger, the trigger is still created.
Como se mencion arriba, usar EXPLAIN PLAN FOR es la manera mas fcil para tener una idea sobre el plan
de ejecucin de una sentencia SQL sin tener que ejecutarla, pero podra no ser el mismo plan usado para
ejecutarla porque la seleccin del plan tiene lugar al momento de la ejecucin y depende de muchos factores
como carga, exactitud de las estadsticas y hints por nombrar algunos factores. De hecho, podras estar ms
interesado en saber el plan de ejecucin de un SQL corriendo ms que en el plan de ejecucin de una sentencia
SQL no ejecutada an; si ese es el caso puedes obtenerlo de esta forma:
SQL>
SQL>
SQL>
SQL>
column
column
column
column
SID format a6
USERNAME format a10
PROGRAM format a50
EVENT format a30