A procedure has two parts: the specification and the body. The procedure specification begins with the keyword PROCEDURE and ends with the procedure name or a parameter list. Parameter declarations are optional. Procedures that take no parameters are written without parentheses.
The procedure body begins with the keyword IS and ends with the keyword END followed by an optional procedure name. The procedure body has three parts: an optional declarative part, an executable part, and an optional exception-handling part.
The declarative part contains declarations of types, cursors, constants, variables, exceptions, and subprograms. These objects are local and cease to exist when you exit the procedure. The executable part contains statements that assign values, control execution, and manipulate Oracle data. The exception-handling part contains exception handlers, which deal with exceptions raised during execution.
PROCEDURE procedure_name (parameter_declaration[, parameter_declaration]...)];
procedure_body ::=
PROCEDURE procedure_name [(parameter_declaration[, parameter_declaration]...)] IS [[object_declaration [object_declaration] ...] [subprogram_declaration [subprogram_declaration] ...]] BEGIN seq_of_statements [EXCEPTION exception_handler [exception_handler] ...] END [procedure_name];
parameter_declaration ::=
parameter_name [IN | OUT | IN OUT] { cursor_name%ROWTYPE | cursor_variable_name%TYPE | plsql_table_name%TYPE | record_name%TYPE | scalar_type_name | table_name%ROWTYPE | table_name.column_name%TYPE | variable_name%TYPE} [{:= | DEFAULT} expression]
object_declaration ::=
{ constant_declaration | cursor_declaration | cursor_variable_declaration | exception_declaration | plsql_table_declaration | record_declaration | variable_declaration}
subprogram_declaration ::=
{function_declaration | procedure_declaration}
A procedure is called as a PL/SQL statement. For example, the procedure raise_salary might be called as follows:
raise_salary(emp_num, amount);
Inside a procedure, an IN parameter acts like a constant. Therefore, it cannot be assigned a value. An OUT parameter acts like an uninitialized variable. So, its value cannot be assigned to another variable or reassigned to itself. An IN OUT parameter acts like an initialized variable. Therefore, it can be assigned a value, and its value can be assigned to another variable. For summary information about the parameter modes, see Table 7 - 1 .
Before exiting a procedure, explicitly assign values to all OUT formal parameters. Otherwise, the values of corresponding actual parameters are indeterminate. If you exit successfully, PL/SQL assigns values to the actual parameters. However, if you exit with an unhandled exception, PL/SQL does not assign values to the actual parameters.
Unlike OUT and IN OUT parameters, IN parameters can be initialized to default values. For more information, see "Parameter Default Values" .
You can write the procedure specification and body as a unit. Or, you can separate the procedure specification from its body. That way, you can hide implementation details by placing the procedure in a package. You can define procedures in a package body without declaring their specifications in the package specification. However, such procedures can be called only from inside the package.
Procedures can be defined using any Oracle tool that supports PL/SQL. To become available for general use, however, procedures must be CREATEd and stored in an Oracle database. You can issue the CREATE PROCEDURE statement interactively from SQL*Plus or Server Manager. For the full syntax of the CREATE PROCEDURE statement, see Oracle7 Server SQL Reference.
PROCEDURE debit_account (acct_id INTEGER, amount REAL) IS old_balance REAL; new_balance REAL; overdrawn EXCEPTION; BEGIN SELECT bal INTO old_balance FROM accts WHERE acctno = acct_id; new_balance := old_balance - amount; IF new_balance < 0 THEN RAISE overdrawn; ELSE UPDATE accts SET bal = new_balance WHERE acctno = acct_id; END IF; EXCEPTION WHEN overdrawn THEN ... END debit_account;
In the following example, you call the procedure using named notation:
debit_account(amount => 500, acct_id => 10261);