Oracle7 Server Application Developer's Guide

Contents Index Home Previous Next

PL/SQL

PL/SQL is a modern, block-structured programming language. It provides you with a number of features that make developing powerful database applications very convenient. For example, PL/SQL provides procedural constructs, such as loops and conditional statements, that you do not find in standard SQL.

You can directly issue SQL data manipulation language (DML) statements inside PL/SQL blocks, and you can use procedures, supplied by Oracle, to perform data definition language (DDL) statements.

PL/SQL code executes on the server, so using PL/SQL allows you to centralize significant parts of your database applications for increased maintainability and security. It also enables you to achieve a significant reduction of network overhead in client/server applications.

Note: Some Oracle tools, such as Oracle Forms, contain a PL/SQL engine, and can execute PL/SQL locally.

You can even use PL/SQL for some database applications in place of 3GL programs that use embedded SQL or the Oracle Call Interface (OCI).

There are several kinds of PL/SQL program units:

For complete information about the PL/SQL language, see the PL/SQL User's Guide and Reference.

Anonymous Blocks

An anonymous PL/SQL block consists of an optional declarative part, an executable part, and one or more optional exception handlers.

You use the declarative part to declare PL/SQL variables, exceptions, and cursors. The executable part contains PL/SQL code and SQL statements, and can contain nested blocks. Exception handlers contain code that is called when the exception is raised, either as a predefined PL/SQL exception (such as NO_DATA_FOUND or ZERO_DIVIDE), or as an exception that you define.

The following short example of a PL/SQL anonymous block prints the names of all employees in department 20 in the EMP table, using the DBMS_OUTPUT package (described [*]):

DECLARE
    emp_name    VARCHAR2(10);
    CURSOR      c1 IS SELECT ename FROM emp
                        WHERE deptno = 20;
BEGIN
    LOOP
        FETCH c1 INTO emp_name;
        EXIT WHEN c1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(emp_name);
    END LOOP;
END;

Note: If you try this block out using SQL*Plus make sure to issue the command SET SERVEROUTPUT ON so that output using the DBMS_OUTPUT procedures such as PUT_LINE is activated. Also, terminate the example with a slash (/) to activate it.

Exceptions allow you to handle Oracle error conditions within PL/SQL program logic. This allows your application to prevent the server from issuing an error that could cause the client application to abort. The following anonymous block handles the predefined Oracle exception NO_DATA_FOUND (which would result in an ORA-01403 error if not handled):

DECLARE
    emp_number   INTEGER := 9999;
    emp_name     VARCHAR2(10);
BEGIN
    SELECT ename INTO emp_name FROM emp
        WHERE empno = emp_number;   -- no such number
    DBMS_OUTPUT.PUT_LINE('Employee name is ' || emp_name);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('No such employee: ' || emp_number);
END;

You can also define your own exceptions, declare them in the declaration part of a block, and define them in the exception part of the block. An example follows:

DECLARE
    emp_name           VARCHAR2(10);
    emp_number         INTEGER;
    empno_out_of_range EXCEPTION;
BEGIN
    emp_number := 10001;
    IF emp_number > 9999 OR emp_number < 1000 THEN
        RAISE empno_out_of_range;
    ELSE
        SELECT ename INTO emp_name FROM emp
            WHERE empno = emp_number;
        DBMS_OUTPUT.PUT_LINE('Employee name is ' || emp_name);
END IF;
EXCEPTION
    WHEN empno_out_of_range THEN
        DBMS_OUTPUT.PUT_LINE('Employee number ' || emp_number ||
          ' is out of range.');
END;

See the PL/SQL User's Guide and Reference for a complete treatment of exceptions.

Anonymous blocks are most often used either interactively, from a tool such as SQL*Plus, or in a precompiler, OCI, or SQL*Module application. They are normally used to call stored procedures, or to open cursor variables. (See [*] for a description of cursor variables.)

Database Triggers

A database trigger is a special kind of PL/SQL anonymous block. You can define triggers to fire before or after SQL statements, either on a statement level or for each row that is affected. See Chapter 9 in this Guide for information about database triggers.

Stored Procedures and Functions

A stored procedure or function is a PL/SQL program unit that

Note: The term stored procedure is sometimes used generically in this Guide to cover both stored procedures and stored functions.

Procedure Names

Since a procedure is stored in the database, it must be named, to distinguish it from other stored procedures, and to make it possible for applications to call it. Each publicly-visible procedure in a schema must have a unique name. The name must be a legal PL/SQL identifier.

Note: If you plan to call a stored procedure using a stub generated by SQL*Module, the stored procedure name must also be a legal identifier in the calling host 3GL language such as Ada or C.

Procedure and function names that are part of packages can be overloaded. That is, you can use the same name for different subprograms as long as their formal parameters differ in number, order, or datatype family. See the PL/SQL User's Guide and Reference for more information about subprogram name overloading.

Procedure Parameters

Stored procedures and functions can take parameters. The following example shows a stored procedure that is similar to the anonymous block [*]:

PROCEDURE get_emp_names (dept_num IN NUMBER) IS
    emp_name       VARCHAR2(10);
    CURSOR         c1 (depno NUMBER) IS
                      SELECT ename FROM emp
                        WHERE deptno = depno;






BEGIN
    OPEN c1(dept_num);
    LOOP
        FETCH c1 INTO emp_name;
        EXIT WHEN c1%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(emp_name);
    END LOOP;
    CLOSE c1;
END;

In the stored procedure example, the department number is an input parameter, which is used when the parameterized cursor C1 is opened.

The formal parameters of a procedure have three major parts:

name The name of the parameter, which must be a legal PL/SQL identifier.
mode The parameter mode, which indicates whether the parameter is an input-only parameter (IN), an output-only parameter (OUT), or is both an input and an output parameter (IN OUT). If the mode is not specified, IN is assumed.
datatype The parameter datatype is a standard PL/SQL datatype.

Parameter Modes

You use parameter modes to define the behavior of formal parameters. The three parameter modes, IN (the default), OUT, and IN OUT, can be used with any subprogram. However, avoid using the OUT and IN OUT modes with functions. The purpose of a function is to take zero or more arguments and return a single value. It is poor programming practice to have a function return multiple values. Also, functions should be free from side effects, which change the values of variables not local to the subprogram.

Table 7 - 1 summarizes the information about parameter modes. Parameter modes are explained in detail in the PL/SQL User's Guide and Reference.

IN OUT IN OUT
the default must be specified must be specified
passes values to a subprogram returns values to the caller passes initial values to a subprogram; returns updated values to the caller
formal parameter acts like a constant formal parameter acts like an uninitialized variable formal parameter acts like an initialized variable
formal parameter cannot be assigned a value formal parameter cannot be used in an expression; must be assigned a value formal parameter should be assigned a value
actual parameter can be a constant, initialized variable, literal, or expression actual parameter must be a variable actual parameter must be a variable
Table 7 - 1. Parameter Modes

Parameter Datatypes

The datatype of a formal parameter consists of one of the following:

Attention: Numerically constrained types such as NUMBER(2) or VARCHAR2(20) are not allowed in a parameter list.

%TYPE and %ROWTYPE Attributes However, you can use the type attributes %TYPE and %ROWTYPE to constrain the parameter. For example, the GET_EMP_NAMES procedure specification [*] could be written as

PROCEDURE get_emp_names(dept_num IN emp.deptno%TYPE)

to have the DEPT_NUM parameter take the same datatype as the DEPTNO column in the EMP table. The column and table must be available when a declaration using %TYPE (or %ROWTYPE) is elaborated.

Using %TYPE is recommended, since if the type of the column in the table changes, it is not necessary to change the application code.

If the GET_EMP_NAMES procedure is part of a package, then you can use previously-declared public (package) variables to constrain a parameter datatype. For example:

dept_number    number(2);
...
PROCEDURE get_emp_names(dept_num IN dept_number%TYPE);

You use the %ROWTYPE attribute to create a record that contains all the columns of the specified table. The following example defines the GET_EMP_REC procedure, that returns all the columns of the EMP table in a PL/SQL record, for the given EMPNO:

PROCEDURE get_emp_rec (emp_number  IN emp.empno%TYPE,
                       emp_ret    OUT emp%ROWTYPE) IS
BEGIN
    SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno
        INTO emp_ret
        FROM emp
        WHERE empno = emp_number;
END;

You could call this procedure from a PL/SQL block as follows:

DECLARE
  emp_row      emp%ROWTYPE;     -- declare a record matching a
                                -- row in the EMP table
BEGIN
  get_emp_rec(7499, emp_row);   -- call for emp# 7499
  DBMS_OUTPUT.PUT(emp_row.ename || ' ' || emp_row.empno);
  DBMS_OUTPUT.PUT(' ' || emp_row.job || ' ' || emp_row.mgr);
  DBMS_OUTPUT.PUT(' ' || emp_row.hiredate || ' ' || emp_row.sal);
  DBMS_OUTPUT.PUT(' ' || emp_row.comm || ' ' || emp_row.deptno);
  DBMS_OUTPUT.NEW_LINE;
END;

Stored functions can also return values that are declared using %ROWTYPE. For example:

FUNCTION get_emp_rec (dept_num IN emp.deptno%TYPE)
    RETURN emp%ROWTYPE IS ...

Tables and Records

You can pass PL/SQL tables as parameters to stored procedures and functions. You can also pass tables of records as parameters.

Default Parameter Values

Parameters can take default values. You use the DEFAULT keyword or the assignment operator to give a parameter a default value. For example, the specification for the GET_EMP_NAMES procedure [*] could be written as

PROCEDURE get_emp_names (dept_num IN NUMBER DEFAULT 20) IS ...

or as

PROCEDURE get_emp_names (dept_num IN NUMBER := 20) IS ...

When a parameter takes a default value, it can be omitted from the actual parameter list when you call the procedure. When you do specify the parameter value on the call, it overrides the default value.

DECLARE Keyword

Unlike in an anonymous PL/SQL block, you do not use the keyword DECLARE before the declarations of variables, cursors, and exceptions in a stored procedure. In fact, it is an error to use it.

Creating Stored Procedures and Functions

Use your normal text editor to write the procedure. At the beginning of the procedure, place the command

CREATE PROCEDURE procedure_name AS   ...

For example, to use the example [*], you can create a text (source) file called get_emp.sql containing the following code:

CREATE PROCEDURE get_emp_rec (emp_number  IN emp.empno%TYPE,
                              emp_ret    OUT emp%ROWTYPE) AS
BEGIN
    SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno
        INTO emp_ret
        FROM emp
        WHERE empno = emp_number;
END;

Then, using an interactive too such as SQL*Plus, load the text file containing the procedure by entering the command

SQLPLUS> @get_emp

to load the procedure into the current schema. (.SQL is the default file extension.) Note the slash (/) at the end of the code. This is not part of the code; it just activates the loading of the procedure.

Note: When developing a new procedure, it is usually much more convenient to use the CREATE OR REPLACE . . . PROCEDURE command. This replaces any previous version of that procedure in the same schema with the newer version. This is done with no warning.

You can use either the keyword IS or AS after the procedure parameter list.

Use the CREATE [OR REPLACE] FUNCTION . . . command to store functions. See the Oracle7 Server SQL Reference for the complete syntax of the CREATE PROCEDURE and CREATE FUNCTION commands.

Privileges Required to Create Procedures and Functions

To create a stand-alone procedure or function, or package specification or body, you must meet the following prerequisites:

Attention: To create without errors, that is, to compile the procedure or package successfully, requires the following additional privileges:

The owner of the procedure or package must have been explicitly granted the necessary object privileges for all objects referenced within the body of the code; the owner cannot have obtained required privileges through roles.

If the privileges of a procedure's or package's owner change, the procedure must be reauthenticated before it is executed. If a necessary privilege to a referenced object is revoked from the owner of the procedure (or package), the procedure cannot be executed.

The EXECUTE privilege on a procedure gives a user the right to execute a procedure owned by another user. Privileged users execute the procedure under the security domain of the procedure's owner. Therefore, users never have to be granted the privileges to the objects referenced by a procedure. This allows for more disciplined and efficient security strategies with database applications and their users. Furthermore, all procedures and packages are stored in the data dictionary (in the SYSTEM tablespace). No quota controls the amount of space available to a user who creates procedures and packages.

Altering Stored Procedures and Functions

To alter a stored procedure or stored function, you must first DROP it, using the DROP PROCEDURE or DROP FUNCTION command, then recreate it using the CREATE PROCEDURE or CREATE FUNCTION command. Alternatively, use the CREATE OR REPLACE PROCEDURE or CREATE OR REPLACE FUNCTION command, which first drops the procedure or function if it exists, then recreates it as specified.

The procedure or function is dropped with no warning.


Contents Index Home Previous Next