db2 SQL Procedural Lang 115
db2 SQL Procedural Lang 115
db2 SQL Procedural Lang 115
IBM
Notices
This information was developed for products and services offered in the US. This material might be
available from IBM in other languages. However, you may be required to own a copy of the product or
product version in that language in order to access it.
IBM may not offer the products, services, or features discussed in this document in other countries.
Consult your local IBM representative for information on the products and services currently available in
your area. Any reference to an IBM product, program, or service is not intended to state or imply that only
that IBM product, program, or service may be used. Any functionally equivalent product, program, or
service that does not infringe any IBM intellectual property right may be used instead. However, it is the
user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service.
IBM may have patents or pending patent applications covering subject matter described in this
document. The furnishing of this document does not grant you any license to these patents. You can send
license inquiries, in writing, to:
For license inquiries regarding double-byte character set (DBCS) information, contact the IBM Intellectual
Property Department in your country or send inquiries, in writing, to:
Each copy or any portion of these sample programs or any derivative work must include a copyright
notice as follows:
© (your company name) (year).
Portions of this code are derived from IBM Corp. Sample Programs.
© Copyright IBM Corp. _enter the year or years_.
Trademarks
IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business
Machines Corp., registered in many jurisdictions worldwide. Other product and service names might be
trademarks of IBM or other companies. A current list of IBM trademarks is available on the web at
"Copyright and trademark information" at www.ibm.com/legal/copytrade.shtml.
Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both.
Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the
United States, other countries, or both.
UNIX is a registered trademark of The Open Group in the United States and other countries.
Java and all Java-based trademarks and logos are trademarks or registered trademarks of Oracle and/or
its affiliates.
ii Notices
Applicability
These terms and conditions are in addition to any terms of use for the IBM website.
Personal use
You may reproduce these publications for your personal, noncommercial use provided that all proprietary
notices are preserved. You may not distribute, display or make derivative work of these publications, or
any portion thereof, without the express consent of IBM.
Commercial use
You may reproduce, distribute and display these publications solely within your enterprise provided that
all proprietary notices are preserved. You may not make derivative works of these publications, or
reproduce, distribute or display these publications or any portion thereof outside your enterprise, without
the express consent of IBM.
Rights
Except as expressly granted in this permission, no other permissions, licenses or rights are granted, either
express or implied, to the publications or any information, data, software or other intellectual property
contained therein.
IBM reserves the right to withdraw the permissions granted herein whenever, in its discretion, the use of
the publications is detrimental to its interest or, as determined by IBM, the above instructions are not
being properly followed.
You may not download, export or re-export this information except in full compliance with all applicable
laws and regulations, including all United States export laws and regulations.
IBM MAKES NO GUARANTEE ABOUT THE CONTENT OF THESE PUBLICATIONS. THE PUBLICATIONS ARE
PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, NON-
INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
Notices iii
iv IBM Db2 V11.5: SQL Procedural Languages (PL/SQL) Support
Contents
Notices...................................................................................................................i
Trademarks...................................................................................................................................................ii
Terms and conditions for product documentation......................................................................................ii
Tables................................................................................................................. vii
v
RAISE statement (PL/SQL)...................................................................................................................67
Oracle-Db2 error mapping (PL/SQL)....................................................................................................68
Cursors (PL/SQL)........................................................................................................................................70
Static cursors (PL/SQL)........................................................................................................................ 70
Cursor variables (PL/SQL).................................................................................................................... 76
Triggers (PL/SQL)....................................................................................................................................... 81
Types of triggers (PL/SQL)....................................................................................................................81
Trigger variables (PL/SQL)....................................................................................................................81
Trigger event predicates (PL/SQL)....................................................................................................... 82
Transactions and exceptions (PL/SQL)................................................................................................82
CREATE TRIGGER statement (PL/SQL)............................................................................................... 83
Dropping triggers (PL/SQL).................................................................................................................. 86
Examples: Triggers (PL/SQL)................................................................................................................86
Packages (PL/SQL).....................................................................................................................................88
Package components (PL/SQL)............................................................................................................88
Creating packages (PL/SQL).................................................................................................................89
Referencing package objects (PL/SQL)................................................................................................94
Dropping packages (PL/SQL)............................................................................................................... 97
Index.................................................................................................................. 99
vi
Tables
1. Collection methods that are supported (or tolerated) by the Db2 data server in a PL/SQL context........ 29
2. Parameter modes........................................................................................................................................35
4. SQL statements that can be executed by the Db2 data server within PL/SQL contexts...........................47
6. Mapping of PL/SQL error codes and exception names to Db2 data server error codes and
SQLSTATE values....................................................................................................................................... 68
vii
viii
Chapter 1. PL/SQL support
PL/SQL (Procedural Language/Structured Query Language) statements can be compiled and executed
using data server interfaces provided by Db2®. This reduces the complexity of enabling existing PL/SQL
solutions to work with the Db2 data server.
The data server interfaces you can use include:
• The Db2 command line processor (CLP)
• CLPPlus
• IBM® Data Studio client
Enablement
To enable this capability, set the DB2_COMPATIBILITY_VECTOR registry variable to hexadecimal 0x800
(bit position 800), then stop and restart the instance:
db2set DB2_COMPATIBILITY_VECTOR=800
db2stop
db2start
To activate all compatibility features for Oracle applications, set the DB2_COMPATIBILITY_VECTOR
registry variable to ORA, then stop and restart the instance:
db2set DB2_COMPATIBILITY_VECTOR=ORA
db2stop
db2start
PL/SQL features
PL/SQL statements and scripts can be compiled and executed using Db2 database server interfaces.
You can execute the following PL/SQL statements:
• Anonymous blocks; for example, DECLARE...BEGIN...END
• CREATE OR REPLACE FUNCTION statement
• CREATE OR REPLACE PACKAGE statement
• CREATE OR REPLACE PACKAGE BODY statement
• CREATE OR REPLACE PROCEDURE statement
• CREATE OR REPLACE TRIGGER statement
• CREATE OR REPLACE TYPE statement
• DROP PACKAGE statement
• DROP PACKAGE BODY statement
PL/SQL procedures and functions can be invoked from other PL/SQL statements or from Db2 SQL PL
statements. You can call a PL/SQL procedure from SQL PL by using the CALL statement.
The following statements and language elements are supported in PL/SQL contexts:
• Type declarations:
– Associative arrays
– Record types
– VARRAY types
• Subtype declarations
Procedure
1. Formulate PL/SQL procedure or function definitions within a CLP script file. Terminate each statement
with a new line and a forward slash character (/).
Other statement termination characters are also supported.
2. Save the file.
In this example, the file name is script.db2.
3. Execute the script from the CLP.
If a forward slash character or a semicolon was used to terminate statements, issue the following
command:
If another statement termination character (for example, the @ character) was used in the script file,
you must specify that character in the command string. For example:
Results
The CLP script should execute successfully if there are no syntax errors.
Example
The following example of a CLP script creates a PL/SQL function and procedure, and then calls the PL/SQL
procedure.
CONNECT TO mydb
/
CALL update_comp('Curly')
CONNECT RESET
/
CALL update_comp('Curly')
Return Status = 0
3 record(s) selected.
What to do next
Test your new procedures or functions by invoking them. For procedures, use the CALL statement. For
functions, execute queries or other SQL statements that contain references to those functions.
--
-- Script that creates the 'sample' tables, views, procedures,
-- functions, triggers, and so on.
--
-- Create and populate tables used in the documentation examples.
--
-- Create the 'dept' table
--
CREATE TABLE dept (
deptno NUMBER(2) NOT NULL CONSTRAINT dept_pk PRIMARY KEY,
Obfuscation
Obfuscation encodes the body of the DDL statements for database objects such as routines, triggers,
views, and PL/SQL packages. Obfuscating your code helps protect your intellectual property because
users cannot read the code, but the Db2 data server can still understand it.
The DBMS_DDL module provides two routines for obfuscating your routines, triggers, views, or your
PL/SQL packages:
WRAP function
Takes a routine, trigger, PL/SQL package, or PL/SQL package body definition as an argument and
produces a string containing the initial header followed by an obfuscated version of the rest of the
statement. For example, input like:
The obfuscated portion of the DDL statement contains codepage invariant characters, ensuring that it
is valid for any codepage.
CREATE_WRAPPED procedure
Takes the same input as the WRAP function described previously, but instead of returning the
obfuscated text, an object is created in the database. Internally the object is not obfuscated so that it
can be processed by the compiler, but in catalog views like SYSCAT.ROUTINES or SYSCAT.TRIGGERS
the content of the TEXT column is obfuscated.
An obfuscated statement can be used in CLP scripts and can be submitted as dynamic SQL using other
client interfaces.
Obfuscation is available for the following statements:
• db2look by using the -wrap option
• CREATE FUNCTION
• CREATE PACKAGE
• CREATE PACKAGE BODY
• CREATE PROCEDURE
• CREATE TRIGGER
• CREATE VIEW
Blocks (PL/SQL)
PL/SQL block structures can be included within PL/SQL procedure, function, or trigger definitions or
executed independently as an anonymous block statement.
PL/SQL block structures and the anonymous block statement contain one or more of the following
sections:
• An optional declaration section
• A mandatory executable section
• An optional exception section
These sections can include SQL statements, PL/SQL statements, data type and variable declarations, or
other PL/SQL language elements.
Invocation
This statement can be executed from an interactive tool or command line interface such as the CLP. This
statement can also be embedded within a PL/SQL procedure definition, function definition, or trigger
definition. Within these contexts, the statement is called a block structure instead of an anonymous block
statement.
Authorization
No privileges are required to invoke an anonymous block. However, the privileges held by the
authorization ID of the statement must include all necessary privileges to invoke the SQL statements that
are embedded within the anonymous block.
BEGIN statement
declaration
DECLARE
END
Description
DECLARE
An optional keyword that starts the DECLARE statement, which can be used to declare data types,
variables, or cursors. The use of this keyword depends upon the context in which the block appears.
declaration
Specifies a data type, variable, cursor, exception, or procedure declaration whose scope is local to the
block. Each declaration must be terminated by a semicolon.
BEGIN
A mandatory keyword that introduces the executable section, which can include one or more SQL or
PL/SQL statements. A BEGIN-END block can contain nested BEGIN-END blocks.
statement
Specifies a PL/SQL or SQL statement. Each statement must be terminated by a semicolon.
EXCEPTION
An optional keyword that introduces the exception section.
WHEN exception-condition
Specifies a conditional expression that tests for one or more types of exceptions.
THEN handler-statement
Specifies a PL/SQL or SQL statement that is executed if a thrown exception matches an exception in
exception-condition. Each statement must be terminated by a semicolon.
END
A mandatory keyword that ends the block.
Examples
The following example shows the simplest possible anonymous block statement that the Db2 data server
can compile:
BEGIN
NULL;
END;
The following example shows an anonymous block that you can enter interactively through theDb2 CLP:
BEGIN
dbms_output.put_line( 'Hello' );
END;
DECLARE
current_date DATE := SYSDATE;
BEGIN
dbms_output.put_line( current_date );
END;
Procedures (PL/SQL)
The Db2 data server supports the compilation and execution of PL/SQL procedures. PL/SQL procedures
are database objects that contain PL/SQL procedural logic and SQL statements that can be invoked in
contexts where the CALL statement or procedure references are valid.
PL/SQL procedures are created by executing the PL/SQL CREATE PROCEDURE statement. Such
procedures can be dropped from the database by using the Db2 SQL DROP statement. If you want to
replace the implementation for a procedure, you do not need to drop it. You can use the CREATE
PROCEDURE statement and specify the OR REPLACE option to replace the procedure implementation.
Invocation
This statement can be executed from the Db2 command line processor (CLP), any supported interactive
SQL interface, an application, or a routine.
Authorization
The privileges held by the authorization ID of the statement must include at least one of the following:
• If the schema name of the procedure does not exist, IMPLICIT_SCHEMA authority on the database
• If the schema name of the procedure refers to an existing schema, CREATEIN privilege on the schema
• DBADM authority
The privileges held by the authorization ID of the statement must also include all of the privileges
necessary to invoke the SQL statements that are specified in the procedure body.
The authorization ID of the statement must be the owner of the matched procedure if OR REPLACE is
specified (SQLSTATE 42501).
( )
,
IN
parameter-name data-type
OUT default-clause
IN OUT
IS BEGIN
READS SQL DATA AS declaration
statement
END
procedure-name
Description
PROCEDURE procedure-name
Specifies an identifier for the procedure. The unqualified form of procedure-name is an SQL identifier
with a maximum length of 128. In dynamic SQL statements, the value of the CURRENT SCHEMA
special register is used to qualify an unqualified object name. In static SQL statements, the
QUALIFIER precompile or bind option implicitly specifies the qualifier for unqualified object names.
The qualified form of procedure-name is a schema name followed by a period character and an SQL
identifier. If a two-part name is specified, the schema name cannot begin with 'SYS'; otherwise, an
error is returned (SQLSTATE 42939).
The name (including an implicit or explicit qualifier), together with the number of parameters, must
not identify a procedure that is described in the catalog (SQLSTATE 42723). The unqualified name,
together with the number of parameters, is unique within its schema, but does not need to be unique
across schemas.
parameter-name
Specifies the name of a parameter. The parameter name must be unique for this procedure
(SQLSTATE 42734).
data-type
Specifies one of the supported PL/SQL data types.
READS SQL DATA
Indicates that SQL statements that do not modify SQL data can be included in the procedure. This
clause is a Db2 data server extension.
IS or AS
Introduces the procedure body definition.
Notes
The CREATE PROCEDURE statement can be submitted in obfuscated form. In an obfuscated statement,
only the procedure name is readable. The rest of the statement is encoded in such a way that it is not
readable, but can be decoded by the database server. Obfuscated statements can be produced by calling
the DBMS_DDL.WRAP function.
Examples
The following example shows a simple procedure that takes no parameters:
The following example shows a procedure that takes an IN and an OUT parameter, and that has GOTO
statements whose labels are of the standard PL/SQL form (<<label>>):
<<LABEL1BELOW>>
out1 := out1 || 'four';
END test_goto;
( )
parameter-value
Description
procedure-name
Specifies an identifier for the procedure.
parameter-value
Specifies a parameter value. If no parameters are to be passed, the procedure can be called either
with or without parentheses.
Example
The following example shows how to call a PL/SQL procedure within a PL/SQL context:
BEGIN
simple_procedure;
END;
After a PL/SQL procedure has been created in a Db2 database, it can also be called using the CALL
statement, which is supported inDb2 SQL contexts and applications using supported Db2 application
programming interfaces.
Examples
DECLARE
cursor1 NUMBER;
rowsProcessed NUMBER;
BEGIN
cursor1 := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor1, 'INSERT INTO T1 VALUES (10)', DBMS_SQL.NATIVE);
rowsProcessed := DBMS_SQL.EXECUTE(cursor1);
DBMS_SQL.CLOSE_CURSOR(cursor1);
END;
/
DECLARE
v_connection UTL_SMTP.CONNECTION;
v_reply UTL_SMTP.REPLY;
BEGIN
UTL_SMTP.OPEN_CONNECTION('127.0.0.1', 25, v_connection, 10, v_reply);
UTL_SMTP.HELO(v_connection,'127.0.0.1');
UTL_SMTP.MAIL(v_connection, '[email protected]');
UTL_SMTP.RCPT(v_connection, '[email protected]');
v_reply := UTL_SMTP.OPEN_DATA (v_connection);
UTL_SMTP.WRITE_DATA (v_connection, 'Test message');
UTL_SMTP.CLOSE_DATA (v_connection);
UTL_SMTP.QUIT(v_connection);
END;
/
Functions (PL/SQL)
The Db2 data server supports the compilation and execution of scalar and pipelined PL/SQL functions.
Scalar PL/SQL functions can be invoked in contexts where expressions are valid. When evaluated, a scalar
PL/SQL function returns a value that is substituted within the expression in which the function is
embedded. Pipelined PL/SQL functions can be invoked in the FROM clause of SELECT statements and
compute a table one row at a time.
PL/SQL functions are created by executing the CREATE FUNCTION statement. Such functions can be
dropped from the database by using the Db2 SQL DROP statement. If you want to replace the
implementation for a function, you do not need to drop it. You can use the CREATE FUNCTION statement
and specify the OR REPLACE option to replace the function implementation.
Invocation
A scalar function returns a single value each time it is invoked, and is generally valid wherever an SQL
expression is valid. A pipelined function computes a table one row at a time and can be referenced in the
FROM clause of SELECT statements.
This statement can be executed from the Db2 command line processor, any supported interactive SQL
interface, an application, or routine.
Authorization
The privileges held by the authorization ID of the statement must include at least one of the following:
• If the schema name of the function does not exist, IMPLICIT_SCHEMA authority on the database
• If the schema name of the function refers to an existing schema, CREATEIN privilege on the schema
• DBADM authority
Syntax
CREATE FUNCTION name
OR REPLACE
( )
,
IN
parameter-name data-type
OUT default-clause
IN OUT
RETURN return-type IS
PIPELINED AS
BEGIN statement
declaration
END
name
Description
The CREATE FUNCTION statement specifies the name of the function, the optional parameters, the return
type of the function, and the body of the function. The body of the function is a block that is enclosed by
the BEGIN and END keywords. It can contain an optional EXCEPTION section that defines an action to be
taken when a defined exception condition occurs.
OR REPLACE
Indicates that if a function with the same name already exists in the schema, the new function is to
replace the existing one. If this option is not specified, the new function cannot replace an existing
one with the same name in the same schema.
FUNCTION name
Specifies an identifier for the function.
parameter-name
Specifies the name of a parameter. The name cannot be the same as any other parameter-name in
the parameter list (SQLSTATE 42734).
data-type
Specifies one of the supported PL/SQL data types.
RETURN return-type
Specifies the data type of the scalar value that is returned by the function.
Notes
A PL/SQL function cannot take any action that changes the state of an object that the database manager
does not manage.
The CREATE FUNCTION statement can be submitted in obfuscated form. In an obfuscated statement,
only the function name is readable. The rest of the statement is encoded in such a way that it is not
readable, but can be decoded by the database server. Obfuscated statements can be produced by calling
the DBMS_DDL.WRAP function.
Examples
The following example shows a basic function that takes no parameters:
The following example shows a function that takes two input parameters:
The following example shows a pipelined function that returns a table with two rows:
Syntax
function-name
,
( parameter-value )
Description
function-name
Specifies an identifier for the function.
parameter-value
Specifies a value for a parameter.
Examples
The following example shows how a function named SIMPLE_FUNCTION, defined in the PL/SQL sample
schema, can be called from a PL/SQL anonymous block:
BEGIN
DBMS_OUTPUT.PUT_LINE(simple_function);
END;
The following example shows how a scalar function and a pipelined function can be used within an SQL
statement:
SELECT
emp.empno, emp.ename, emp.sal, emp.comm,
emp_comp(sal, comm)+bon.bonus "YEARLY COMPENSATION"
FROM emp, TABLE(bonuses()) as bon(category, bonus)
WHERE bon.category = emp.category
Syntax
TYPE varraytype IS VARRAY ( n ) OF datatype ;
Example
The following example reads employee names from the EMP table, stores the names in an array variable
of type VARRAY, and then displays the results. The EMP table contains one column named ENAME. The
code is executed from a Db2 script (script.db2). The following commands should be issued from the
Db2 command window before executing the script (db2 -tvf script.db2):
db2set DB2_COMPATIBILITY_VECTOR=FFF
db2stop
db2start
connect to mydb
/
SET SERVEROUTPUT ON
/
DECLARE
emp_arr foo.emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 5;
i INTEGER := 0;
BEGIN
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp.ename;
END LOOP;
FOR j IN 1..5 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j));
END LOOP;
END;
/
connect reset
/
Curly
Larry
Moe
Shemp
Joe
Invocation
This statement can be executed from the Db2 command line processor (CLP), any supported interactive
SQL interface, an application, or a routine.
Authorization
The privileges held by the authorization ID of the statement must include at least one of the following:
• If the schema name of the VARRAY type does not exist, IMPLICIT_SCHEMA authority on the database
• If the schema name of the VARRAY type refers to an existing schema, CREATEIN privilege on the
schema
• DBADM authority
Syntax
CREATE TYPE varraytype IS VARRAY ( n
OR REPLACE AS
) OF datatype
Description
OR REPLACE
Indicates that if a user-defined data type with the same name already exists in the schema, the new
data type is to replace the existing one. If this option is not specified, the new data type cannot
replace an existing one with the same name in the same schema.
varraytype
Specifies an identifier for the VARRAY type. The unqualified form of varraytype is an SQL identifier
with a maximum length of 128. The value of the CURRENT SCHEMA special register is used to qualify
an unqualified object name. The qualified form of varraytype is a schema name followed by a period
character and an SQL identifier. If a two-part name is specified, the schema name cannot begin with
'SYS'; otherwise, an error is returned (SQLSTATE 42939). The name (including an implicit or explicit
qualifier) must not identify a user-defined data type that is described in the catalog (SQLSTATE
42723). The unqualified name is unique within its schema, but does not need to be unique across
schemas.
n
Specifies the maximum number of elements in the array type. The maximum cardinality of an array on
a given system is limited by the total amount of memory that is available to Db2 applications. As such,
although arrays of large cardinalities (up to 2,147,483,647) can be created, not all elements might be
available for use.
datatype
A supported data type, such as NUMBER, VARCHAR2, RECORD, VARRAY, or associative array type.
The %TYPE attribute and the %ROWTYPE attribute are also supported.
Example
The following example creates a VARRAY data type with a maximum of 10 elements, where each element
has the data type NUMBER:
Invocation
This statement can be executed from the Db2 command line processor (CLP), any supported interactive
SQL interface, an application, or a routine.
Authorization
The privileges held by the authorization ID of the statement must include at least one of the following:
• If the schema name of the nested table type does not exist, IMPLICIT_SCHEMA authority on the
database
• If the schema name of the nested table type refers to an existing schema, CREATEIN privilege on the
schema
• DBADM authority
Syntax
CREATE TYPE assocarray IS TABLE OF
OR REPLACE AS
datatype
Description
OR REPLACE
Indicates that if a user-defined data type with the same name already exists in the schema, the new
data type is to replace the existing one. If this option is not specified, the new data type cannot
replace an existing one with the same name in the same schema.
assocarray
Specifies an identifier for the associative array type.
datatype
Specifies a supported data type, such as NUMBER, VARCHAR2, RECORD, VARRAY, or associative
array type.
Example
The following example reads the first ten employee names from the EMP table, stores them in a nested
table, and then displays its contents:
SET SERVEROUTPUT ON
/
DECLARE
emp_arr emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j));
END LOOP;
END
/
Syntax
,
Description
TYPE rectype IS RECORD
Specifies an identifier for the record type.
field
Specifies an identifier for a field of the record type.
datatype
Specifies the corresponding data type of the field. The %TYPE attribute, RECORD, VARRAY,
associative array types, and the %ROWTYPE attributes are supported.
Example
The following example shows a package that references a user-defined record type:
Invocation
This statement can be executed from the Db2 command line processor (CLP), any supported interactive
SQL interface, an application, or a routine.
Authorization
The privileges held by the authorization ID of the statement must include at least one of the following:
• If the schema name of the object type does not exist, IMPLICIT_SCHEMA authority on the database
• If the schema name of the object type refers to an existing schema, CREATEIN privilege on the schema
• DBADM authority
( field datatype )
Description
OR REPLACE
Indicates that if a user-defined data type with the same name already exists in the schema, the new
data type is to replace the existing one. If this option is not specified, the new data type cannot
replace an existing one with the same name in the same schema.
objecttype
Specifies an identifier for the record type.
field
Specifies an identifier for a field of the record type.
datatype
Specifies a supported data type, such as NUMBER, VARCHAR2, RECORD, VARRAY, or associative
array type.
Example
The following example shows a the definition of a record type with two fields:
BINARY_INTEGER
PLS_INTEGER
VARCHAR2 ( n )
BYTE
CHAR
Description
TYPE assoctype
Specifies an identifer for the array type.
datatype
Specifies a supported data type, such as VARCHAR2, NUMBER, RECORD, VARRAY, or associative
array type. The %TYPE attribute and the %ROWTYPE attribute are also supported.
INDEX BY
Specifies that the associative array is to be indexed by one of the data types introduced by this clause.
BINARY INTEGER
Integer numeric data.
PLS_INTEGER
Integer numeric data.
VARCHAR2 (n[BYTE|CHAR])
A variable-length character string of maximum length n code units, which may range from 1 to
32 672 BYTE or from 1 to 8 168 CHAR. The %TYPE attribute is also supported if the object to
which the %TYPE attribute is being applied is of the BINARY_INTEGER, PLS_INTEGER, or
VARCHAR2 data type.
To declare a variable with an associative array type, specify array-name assoctype, where array-
name represents an identifier that is assigned to the associative array, and assoctype represents the
identifier for a previously declared array type.
To reference a particular element of the array, specify array-name(n), where array-name represents
the identifier for a previously declared array, and n represents a value of INDEX BY data type of assoctype.
If the array is defined from a record type, the reference becomes array-name(n).field, where field is
defined within the record type from which the array type is defined. To reference the entire record, omit
field.
Examples
The following example reads the first ten employee names from the EMP table, stores them in an array,
and then displays the contents of the array.
SET SERVEROUTPUT ON
/
DECLARE
emp_arr pkg_test_type1.emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp.ename;
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
The example can be modified to use a record type in the array definition.
SET SERVEROUTPUT ON
/
DECLARE
emp_arr pkg_test_type3.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i).empno := r_emp.empno;
emp_arr(i).ename := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/
EMPNO ENAME
----- -------
1001 SMITH
1002 ALLEN
1003 WARD
1004 JONES
1005 MARTIN
1006 BLAKE
1007 CLARK
1008 SCOTT
1009 KING
1010 TURNER
SET SERVEROUTPUT ON
/
DECLARE
emp_arr pkg_test_type4.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i).empno := r_emp.empno;
emp_arr(i).ename := r_emp.ename;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/
In this case, the sample output is identical to that of the previous example.
Finally, instead of assigning each field of the record individually, a record-level assignment can be made
from r_emp to emp_arr:
SET SERVEROUTPUT ON
/
DECLARE
emp_arr pkg_test_type6.emp_arr_typ;
CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10;
i INTEGER := 0;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr(i) := r_emp;
END LOOP;
FOR j IN 1..10 LOOP
DBMS_OUTPUT.PUT_LINE(emp_arr(j).empno || ' ' ||
emp_arr(j).ename);
END LOOP;
END
/
db2set DB2_COMPATIBILITY_VECTOR=ORA
db2stop
db2start
db2 connect to mydb
The MYDB database has one table, EMP, which has one column, ENAME (defined as VARCHAR(10)):
ENAME
----------
Curly
Larry
Moe
Shemp
Joe
5 record(s) selected.
Table 1. Collection methods that are supported (or tolerated) by the Db2 data server in a PL/SQL context
Collection method Description Example
COUNT Returns the
number of CREATE PACKAGE foo
elements in a AS
TYPE sparse_arr_typ IS TABLE OF NUMBER
collection. INDEX BY BINARY_INTEGER;
END;
/
SET SERVEROUTPUT ON
/
DECLARE
sparse_arr foo.sparse_arr_typ;
BEGIN
sparse_arr(-10) := -10;
sparse_arr(0) := 0;
sparse_arr(10) := 10;
DBMS_OUTPUT.PUT_LINE('COUNT: ' ||
sparse_arr.COUNT);
END;
/
SET SERVEROUTPUT ON
/
DECLARE
actor_names foo.names_typ;
BEGIN
actor_names(1) := 'Chris';
actor_names(2) := 'Steve';
actor_names(3) := 'Kate';
actor_names(4) := 'Naomi';
actor_names(5) := 'Peter';
actor_names(6) := 'Philip';
actor_names(7) := 'Michael';
actor_names(8) := 'Gary';
DBMS_OUTPUT.PUT_LINE('COUNT: ' ||
actor_names.COUNT);
actor_names.DELETE(2);
DBMS_OUTPUT.PUT_LINE('COUNT: ' ||
actor_names.COUNT);
actor_names.DELETE(3, 5);
DBMS_OUTPUT.PUT_LINE('COUNT: ' ||
actor_names.COUNT);
actor_names.DELETE;
DBMS_OUTPUT.PUT_LINE('COUNT: ' ||
actor_names.COUNT);
END;
/
SET SERVEROUTPUT ON
/
DECLARE
emp_arr foo.emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp
WHERE ROWNUM <= 5;
i INTEGER := 0;
BEGIN
FOR r_emp IN emp_cur LOOP
i := i + 1;
emp_arr.EXTEND;
emp_arr(i) := r_emp.ename;
END LOOP;
emp_arr.TRIM;
FOR j IN 1..5 LOOP
IF emp_arr.EXISTS(j) = true THEN
DBMS_OUTPUT.PUT_LINE(emp_arr(j));
ELSE
DBMS_OUTPUT.PUT_LINE('THIS ELEMENT
HAS BEEN DELETED');
END IF;
END LOOP;
END;
/
SET SERVEROUTPUT ON
/
DECLARE
emp_arr foo.emp_arr_typ;
CURSOR emp_cur IS SELECT ename FROM emp
WHERE ROWNUM <= 5;
i INTEGER := 0;
k INTEGER := 0;
l INTEGER := 0;
BEGIN
emp_arr.TRIM;
DBMS_OUTPUT.PUT_LINE('COUNT: ' || emp_arr.COUNT);
emp_arr.TRIM(2);
DBMS_OUTPUT.PUT_LINE('COUNT: ' || emp_arr.COUNT);
END;
/
Variables (PL/SQL)
Variables must be declared before they are referenced.
Variables that are used in a block must generally be defined in the declaration section of the block unless
they are global variables or package-level variables. The declaration section contains the definitions of
variables, cursors, and other types that can be used in PL/SQL statements within the block. A variable
declaration consists of a name that is assigned to the variable and the data type of the variable.
Optionally, the variable can be initialized to a default value within the variable declaration.
Procedures and functions can have parameters for passing input values. Procedures can also have
parameters for passing output values, or parameters for passing both input and output values.
PL/SQL also includes variable data types to match the data types of existing columns, rows, or cursors
using the %TYPE and %ROWTYPE qualifiers.
:= expression
DEFAULT NULL
Description
name
Specifies an identifier that is assigned to the variable.
CONSTANT
Specifies that the variable value is constant. A default expression must be assigned, and a new value
cannot be assigned to the variable within the application program.
type
Specifies a data type for the variable.
NOT NULL
Currently ignored by Db2. Routines that specify NOT NULL for variable declarations compile
successfully. However, such routines behave as though NOT NULL has not been specified. No run-
time checking is performed to disallow null values in variables declared NOT NULL. See the following
example, if your application needs to restrict null values in PL/SQL variables.
DEFAULT
Specifies a default value for the variable. This default is evaluated every time that the block is entered.
For example, if SYSDATE has been assigned to a variable of type DATE, the variable resolves to the
current invocation time, not to the time at which the procedure or function was precompiled.
:=
The assignment operator is a synonym for the DEFAULT keyword. However, if this operator is
specified without expression, the variable is initialized to the value NULL.
expression
Specifies the initial value that is to be assigned to the variable when the block is entered.
NULL
Specifies the SQL value NULL, which has a null value.
Examples
1. The following procedure shows variable declarations that utilize defaults consisting of string and
numeric expressions:
CALL dept_salary_rpt(20);
2. The following example restricts null values by adding explicit checks using IS NULL or IS NOT NULL
and handles error cases as required:
declare
N integer not null := 0;
null_variable exception;
begin
select col1 into N from T;
if N is null then
raise null_variable;
end if;
exception
when null_variable then
-- Handle error condition here.
dbms_output.put_line('Null variable detected');
end;
1. If the string units of the environment is set to CODEUNITS32, the CHAR attribute of the length is implicit. This behavior
is similar to NLS_LENGTH_SEMANTICS=CHAR in an Oracle database.
2. When the DB2_COMPATIBILITY_VECTOR registry variable is set for the DATE data type, DATE is equivalent to
TIMESTAMP (0).
3. National character strings are synonyms for character strings or graphic strings with the mapping of data types
determined by the NCHAR_MAPPING configuration parameter. See “National character strings” for details.
4. For restrictions on the NCLOB data type in certain database environments, see "Restrictions on PL/SQL support".
5. This data type is supported when the number_compat database configuration parameter set to ON.
6. This data type is supported when the varchar2_compat database configuration parameter set to ON.
In addition to the scalar data types described in Table 3 on page 36, the Db2 data server also supports
collection types, record types, and REF CURSOR types.
Syntax
name table . column %TYPE
view
variable
Description
name
Specifies an identifier for the variable or formal parameter that is being declared.
table
Specifies an identifier for the table whose column is to be referenced.
view
Specifies an identifier for the view whose column is to be referenced.
column
Specifies an identifier for the table or view column that is to be referenced.
variable
Specifies an identifier for a previously declared variable that is to be referenced. The variable does not
inherit any other column attributes, such as, for example, the nullability attribute.
Example
The following example shows a procedure that queries the EMP table using an employee number,
displays the employee's data, finds the average salary of all employees in the department to which the
employee belongs, and then compares the chosen employee's salary with the department average.
This procedure could be rewritten without explicitly coding the EMP table data types in the declaration
section.
The p_empno parameter is an example of a formal parameter that is defined using the %TYPE attribute.
The v_avgsal variable is an example of the %TYPE attribute referring to another variable instead of a table
column.
The following sample output is generated by a call to the EMP_SAL_QUERY procedure:
CALL emp_sal_query(7698);
Employee # : 7698
Name : BLAKE
Syntax
SUBTYPE type-name IS built-in-type
Description
SUBTYPE type-name
Specifies an identifier for the subtype. You cannot specify BOOLEAN as the built-in type.
built-in-type
Specifies the built-in data type that the subtype is based on.
RANGE start-value .. end-value
Optionally defines a range of values within the domain of the subtype that is valid for the subtype.
NOT NULL
Optionally defines that the subtype is not nullable.
Example
The following example shows a package that defines a subtype for small integers:
view
Description
record
Specifies an identifier for the record.
table
Specifies an identifier for the table whose column definitions will be used to define the fields in the
record.
view
Specifies an identifier for the view whose column definitions will be used to define the fields in the
record.
%ROWTYPE
Specifies that the record field data types are to be derived from the column data types that are
associated with the identified table or view. Record fields do not inherit any other column attributes,
such as, for example, the nullability attribute.
Example
The following example shows how to use the %ROWTYPE attribute to create a record (named r_emp)
instead of declaring individual variables for the columns in the EMP table.
Syntax
NULL
Examples
The following example shows the simplest valid PL/SQL program that the Db2 data server can compile:
BEGIN
NULL;
END;
The following example shows the NULL statement within an IF...THEN...ELSE statement:
Syntax
variable := expression
Description
variable
Specifies an identifier for a previously-declared variable, OUT formal parameter, or IN OUT formal
parameter.
expression
Specifies an expression that evaluates to a single value. The data type of this value must be
compatible with the data type of variable.
Example
The following example shows assignment statements in the executable section of a procedure:
DBMS_OUTPUT.PUT_LINE(rpt_title);
DBMS_OUTPUT.PUT_LINE('Base Annual Salary: ' || p_base_annual);
END
/
Invocation
This statement can only be specified in a PL/SQL context.
Authorization
The authorization rules are those defined for the specified SQL statement.
The authorization ID of the statement might be affected by the DYNAMICRULES bind option.
Syntax
EXECUTE IMMEDIATE sql-expression
INTO variable
,
IN
USING expression
IN OUT variable
OUT variable
Description
sql-expression
An expression returning the statement string to be executed. The expression must return a character-
string type that is less than the maximum statement size of 2 097 152 bytes. Note that a
CLOB(2097152) can contain a maximum size statement, but a VARCHAR cannot.
The statement string must be one of the following SQL statements:
Notes
• Statement caching affects the behavior of an EXECUTE IMMEDIATE statement.
Example
EXECUTE IMMEDIATE 'BEGIN proc1( :1, :2, :3 ); END' USING IN p1 + 10, IN OUT p3,
OUT p2;
EXECUTE IMMEDIATE 'BEGIN proc1( :1, :2, :3 ); END' INTO p3, p2 USING p1 + 10, p3;
Table 4. SQL statements that can be executed by the Db2 data server within PL/SQL contexts
Command Description
DELETE Deletes rows from a table
INSERT Inserts rows into a table
MERGE Updates a target (a table or view) using data from a
source (result of a table reference)
SELECT INTO Retrieves rows from a table
UPDATE Updates rows in a table
Syntax
,
Description
BULK COLLECT INTO array-variable
Identifies one or more variables with an array data type. Each row of the result is assigned to an
element in each array in the order of the result set, with the array index assigned in sequence.
• If exactly one array-variable is specified:
Notes
• Variations of the BULK COLLECT INTO clause are also supported with the FETCH statement and the
EXECUTE IMMEDIATE statement.
Example
The following example shows a procedure that uses the BULK COLLECT INTO clause to return an array of
rows from the procedure. The procedure and the type for the array are defined in a package.
PROCEDURE get_dept_empno (
dno IN emp.deptno%TYPE,
emps_dno OUT emps_array
);
END bci_sample;
Syntax
insert-statement RETURNING * INTO
,
update-statement
delete-statement expr
record
,
field
Description
insert-statement
Specifies a valid INSERT statement. An exception is raised if the INSERT statement returns a result
set that contains more than one row.
update-statement
Specifies a valid UPDATE statement. An exception is raised if the UPDATE statement returns a result
set that contains more than one row.
delete-statement
Specifies a valid DELETE statement. An exception is raised if the DELETE statement returns a result
set that contains more than one row.
RETURNING *
Specifies that all of the values from the row that is affected by the INSERT, UPDATE, or DELETE
statement are to be made available for assignment.
RETURNING expr
Specifies an expression to be evaluated against the row that is affected by the INSERT, UPDATE, or
DELETE statement. The evaluated results are assigned to a specified record or fields.
INTO record
Specifies that the returned values are to be stored in a record with compatible fields and data types.
The fields must match in number, order, and data type those values that are specified with the
RETURNING clause. If the result set contains no rows, the fields in the record are set to the null value.
INTO field
Specifies that the returned values are to be stored in a set of variables with compatible fields and data
types. The fields must match in number, order, and data type those values that are specified with the
RETURNING clause. If the result set contains no rows, the fields are set to the null value.
Examples
The following example shows a procedure that uses the RETURNING INTO clause:
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Updated Employee # : ' || v_empno);
DBMS_OUTPUT.PUT_LINE('Name : ' || v_ename);
DBMS_OUTPUT.PUT_LINE('Job : ' || v_job);
DBMS_OUTPUT.PUT_LINE('Department : ' || v_deptno);
DBMS_OUTPUT.PUT_LINE('New Salary : ' || v_sal);
DBMS_OUTPUT.PUT_LINE('New Commission : ' || v_comm);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee # ' || p_empno || ' not found');
END IF;
END;
The following example shows a procedure that uses the RETURNING INTO clause with record types:
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Deleted Employee # : ' || r_emp.empno);
DBMS_OUTPUT.PUT_LINE('Name : ' || r_emp.ename);
DBMS_OUTPUT.PUT_LINE('Job : ' || r_emp.job);
DBMS_OUTPUT.PUT_LINE('Manager : ' || r_emp.mgr);
DBMS_OUTPUT.PUT_LINE('Hire Date : ' || r_emp.hiredate);
DBMS_OUTPUT.PUT_LINE('Salary : ' || r_emp.sal);
DBMS_OUTPUT.PUT_LINE('Commission : ' || r_emp.comm);
DBMS_OUTPUT.PUT_LINE('Department : ' || r_emp.deptno);
ELSE
DBMS_OUTPUT.PUT_LINE('Employee # ' || p_empno || ' not found');
END IF;
END;
EXEC emp_delete(9503);
BEGIN
INSERT INTO emp (empno,ename,job,sal,deptno)
VALUES (9001, 'JONES', 'CLERK', 850.00, 40);
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Row has been inserted');
END IF;
END;
• The SQL%NOTFOUND attribute has a Boolean value that returns TRUE if no rows were affected by an
INSERT, UPDATE, or DELETE statement, or if a SELECT INTO statement did not retrieve a row. For
example:
BEGIN
UPDATE emp SET hiredate = '03-JUN-07' WHERE empno = 9000;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No rows were updated');
END IF;
END;
• The SQL%ROWCOUNT attribute has an integer value that represents the number of rows that were
affected by an INSERT, UPDATE, or DELETE statement. For example:
BEGIN
UPDATE emp SET hiredate = '03-JUN-07' WHERE empno = 9001;
DBMS_OUTPUT.PUT_LINE('# rows updated: ' || SQL%ROWCOUNT);
END;
IF statement (PL/SQL)
Use the IF statement within PL/SQL contexts to execute SQL statements on the basis of certain criteria.
The four forms of the IF statement are:
• IF...THEN...END IF
• IF...THEN...ELSE...END IF
• IF...THEN...ELSE IF...END IF
• IF...THEN...ELSIF...THEN...ELSE...END IF
IF...THEN...END IF
The syntax of this statement is:
IF boolean-expression THEN
statements
END IF;
DECLARE
v_empno emp.empno%TYPE;
v_comm emp.comm%TYPE;
CURSOR emp_cursor IS SELECT empno, comm FROM emp;
BEGIN
OPEN emp_cursor;
DBMS_OUTPUT.PUT_LINE('EMPNO COMM');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH emp_cursor INTO v_empno, v_comm;
EXIT WHEN emp_cursor%NOTFOUND;
--
-- Test whether or not the employee gets a commission
--
IF v_comm IS NOT NULL AND v_comm > 0 THEN
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' ||
TO_CHAR(v_comm,'$99999.99'));
END IF;
END LOOP;
CLOSE emp_cursor;
END;
EMPNO COMM
----- -------
7499 $300.00
7521 $500.00
7654 $1400.00
IF...THEN...ELSE...END IF
The syntax of this statement is:
IF boolean-expression THEN
statements
ELSE
statements
END IF;
IF...THEN...ELSE statements specify an alternative set of statements that should be executed if the
condition evaluates to FALSE. In the following example, the previous example is modified so that an
IF...THEN...ELSE statement is used to display the text "Non-commission" if an employee does not have a
commission.
DECLARE
v_empno emp.empno%TYPE;
v_comm emp.comm%TYPE;
CURSOR emp_cursor IS SELECT empno, comm FROM emp;
BEGIN
OPEN emp_cursor;
DBMS_OUTPUT.PUT_LINE('EMPNO COMM');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH emp_cursor INTO v_empno, v_comm;
EXIT WHEN emp_cursor%NOTFOUND;
--
-- Test whether or not the employee gets a commission
--
IF v_comm IS NOT NULL AND v_comm > 0 THEN
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' ||
TO_CHAR(v_comm,'$99999.99'));
ELSE
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || 'Non-commission');
END IF;
END LOOP;
CLOSE emp_cursor;
END;
IF...THEN...ELSE IF...END IF
The syntax of this statement is:
IF boolean-expression THEN
IF boolean-expression THEN
statements
ELSE
IF boolean-expression THEN
statements
END IF;
You can nest IF statements so that alternative IF statements are invoked, depending on whether the
conditions of an outer IF statement evaluate to TRUE or FALSE. In the following example, the outer
IF...THEN...ELSE statement tests whether or not an employee has a commission. The inner
IF...THEN...ELSE statements subsequently test whether the employee's total compensation exceeds or is
less than the company average. When you use this form of the IF statement, you are actually nesting an
IF statement inside of the ELSE part of an outer IF statement. You therefore need one END IF for each
nested IF and one for the parent IF...ELSE. (Note that the logic in this program can be simplified
considerably by calculating each employee's yearly compensation using an NVL function within the
SELECT statement of the cursor declaration; however, the purpose of this example is to demonstrate how
IF statements can be used.)
DECLARE
v_empno emp.empno%TYPE;
v_sal emp.sal%TYPE;
v_comm emp.comm%TYPE;
v_avg NUMBER(7,2);
CURSOR emp_cursor IS SELECT empno, sal, comm FROM emp;
BEGIN
--
-- Calculate the average yearly compensation
--
SELECT AVG((sal + NVL(comm,0)) * 24) INTO v_avg FROM emp;
DBMS_OUTPUT.PUT_LINE('Average Yearly Compensation: ' ||
TO_CHAR(v_avg,'$999,999.99'));
OPEN emp_cursor;
DBMS_OUTPUT.PUT_LINE('EMPNO YEARLY COMP');
DBMS_OUTPUT.PUT_LINE('----- -----------');
LOOP
FETCH emp_cursor INTO v_empno, v_sal, v_comm;
EXIT WHEN emp_cursor%NOTFOUND;
--
-- Test whether or not the employee gets a commission
--
IF v_comm IS NOT NULL AND v_comm > 0 THEN
--
-- Test whether the employee's compensation with commission exceeds
-- the company average
--
IF (v_sal + v_comm) * 24 > v_avg THEN
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' ||
TO_CHAR((v_sal + v_comm) * 24,'$999,999.99') ||
' Exceeds Average');
ELSE
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' ||
TO_CHAR((v_sal + v_comm) * 24,'$999,999.99') ||
IF...THEN...ELSIF...THEN...ELSE...END IF
The syntax of this statement is:
IF boolean-expression THEN
statements
[ ELSIF boolean-expression THEN
statements
[ ELSIF boolean-expression THEN
statements ] ...]
[ ELSE
statements ]
END IF;
IF...THEN...ELSIF...ELSE statements provide the means for checking many alternatives in one statement.
Formally, this statement is equivalent to nested IF...THEN...ELSE...IF...THEN statements, but only one
END IF is needed. The following example uses an IF...THEN...ELSIF...ELSE statement to count the number
of employees by compensation, in steps of $25,000.
DECLARE
v_empno emp.empno%TYPE;
v_comp NUMBER(8,2);
v_lt_25K SMALLINT := 0;
v_25K_50K SMALLINT := 0;
v_50K_75K SMALLINT := 0;
v_75K_100K SMALLINT := 0;
v_ge_100K SMALLINT := 0;
CURSOR emp_cursor IS SELECT empno, (sal + NVL(comm,0)) * 24 FROM emp;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_empno, v_comp;
EXIT WHEN emp_cursor%NOTFOUND;
IF v_comp < 25000 THEN
v_lt_25K := v_lt_25K + 1;
ELSIF v_comp < 50000 THEN
v_25K_50K := v_25K_50K + 1;
Syntax
CASE selector-expression
END CASE
ELSE statements
Description
CASE selector-expression
Specifies an expression whose value has a data type that is compatible with each match-expression. If
the value of selector-expression matches the first match-expression, the statements in the
corresponding THEN clause are executed. If there are no matches, the statements in the
corresponding ELSE clause are executed. If there are no matches and there is no ELSE clause, an
exception is thrown.
Example
The following example uses a simple CASE statement to assign a department name and location to a
variable that is based upon the department number.
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_deptno emp.deptno%TYPE;
v_dname dept.dname%TYPE;
v_loc dept.loc%TYPE;
CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp;
BEGIN
OPEN emp_cursor;
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME DEPTNO DNAME '
|| ' LOC');
DBMS_OUTPUT.PUT_LINE('----- ------- ------ ----------'
|| ' ---------');
LOOP
FETCH emp_cursor INTO v_empno, v_ename, v_deptno;
EXIT WHEN emp_cursor%NOTFOUND;
CASE v_deptno
WHEN 10 THEN v_dname := 'Accounting';
v_loc := 'New York';
WHEN 20 THEN v_dname := 'Research';
v_loc := 'Dallas';
WHEN 30 THEN v_dname := 'Sales';
v_loc := 'Chicago';
WHEN 40 THEN v_dname := 'Operations';
v_loc := 'Boston';
ELSE v_dname := 'unknown';
v_loc := '';
END CASE;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || RPAD(v_ename, 10) ||
' ' || v_deptno || ' ' || RPAD(v_dname, 14) || ' ' ||
v_loc);
END LOOP;
CLOSE emp_cursor;
END;
Syntax
Description
CASE
A keyword that introduces the first WHEN clause in the CASE statement.
WHEN boolean-expression
Specifies an expression that is evaluated when control flow enters the WHEN clause in which the
expression is defined. If boolean-expression evaluates to TRUE, the statements in the corresponding
THEN clause are executed. If boolean-expression does not evaluate to TRUE, the statements in the
corresponding ELSE clause are executed.
THEN
A keyword that introduces the statements that are to be executed when the corresponding Boolean
expression evaluates to TRUE.
statements
Specifies one or more SQL or PL/SQL statements, each terminated with a semicolon.
ELSE
A keyword that introduces the default case of the CASE statement.
Example
The following example uses a searched CASE statement to assign a department name and location to a
variable that is based upon the department number.
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_deptno emp.deptno%TYPE;
v_dname dept.dname%TYPE;
v_loc dept.loc%TYPE;
CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp;
BEGIN
OPEN emp_cursor;
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME DEPTNO DNAME '
|| ' LOC');
DBMS_OUTPUT.PUT_LINE('----- ------- ------ ----------'
|| ' ---------');
LOOP
FETCH emp_cursor INTO v_empno, v_ename, v_deptno;
EXIT WHEN emp_cursor%NOTFOUND;
CASE
WHEN v_deptno = 10 THEN v_dname := 'Accounting';
v_loc := 'New York';
WHEN v_deptno = 20 THEN v_dname := 'Research';
v_loc := 'Dallas';
WHEN v_deptno = 30 THEN v_dname := 'Sales';
v_loc := 'Chicago';
WHEN v_deptno = 40 THEN v_dname := 'Operations';
v_loc := 'Boston';
ELSE v_dname := 'unknown';
v_loc := '';
END CASE;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || RPAD(v_ename, 10) ||
' ' || v_deptno || ' ' || RPAD(v_dname, 14) || ' ' ||
v_loc);
END LOOP;
Loops (PL/SQL)
Use the EXIT, FOR, LOOP, and WHILE statements to repeat a series of commands in your PL/SQL
program.
Invocation
This statement can be invoked within a PL/SQL procedure, function, trigger, or anonymous block.
Authorization
No specific authorization is required to reference a row expression within an SQL statement; however, for
successful statement execution, all other authorization requirements for processing a cursor are required.
Syntax
FOR record IN cursor LOOP statements END LOOP
Description
FOR
Introduces the condition that must be true if the FOR loop is to proceed.
record
Specifies an identifier that was assigned to an implicitly declared record with definition cursor
%ROWTYPE.
IN cursor
Specifies the name of a previously declared cursor.
LOOP and END LOOP
Starts and ends the loop containing SQL statements that are to be executed during each iteration
through the loop.
statements
One or more PL/SQL statements. A minimum of one statement is required.
Invocation
This statement can be embedded within a PL/SQL procedure, function, or anonymous block statement.
Authorization
No privileges are required to invoke the FOR statement; however, the authorization ID of the statement
must hold the necessary privileges to invoke the SQL statements that are embedded in the FOR
statement.
Syntax
FOR integer-variable IN expression1 .. expression2
REVERSE
Description
integer-variable
An automatically defined integer variable that is used during loop processing. The initial value of
integer-variable is expression1. After the initial iteration, the value of integer-variable is incremented
at the beginning of each subsequent iteration. Both expression1 and expression2 are evaluated when
entering the loop, and loop processing stops when integer-variable is equal to expression2.
IN
Introduces the optional REVERSE keyword and expressions that define the range of integer variables
for the loop.
REVERSE
Specifies that the iteration is to proceed from expression2 to expression1. Note that expression2 must
have a higher value than expression1, regardless of whether the REVERSE keyword is specified, if the
statements in the loop are to be processed.
expression1
Specifies the initial value of the range of integer variables for the loop. If the REVERSE keyword is
specified, expression1 specifies the end value of the range of integer variables for the loop.
expression2
Specifies the end value of the range of integer variables for the loop. If the REVERSE keyword is
specified, expression2 specifies the initial value of the range of integer variables for the loop.
statements
Specifies the PL/SQL and SQL statements that are executed each time that the loop is processed.
BEGIN
FOR i IN 1 .. 10 LOOP
DBMS_OUTPUT.PUT_LINE('Iteration # ' || i);
END LOOP;
END;
Iteration # 1
Iteration # 2
Iteration # 3
Iteration # 4
Iteration # 5
Iteration # 6
Iteration # 7
Iteration # 8
Iteration # 9
Iteration # 10
If the start value is greater than the end value, the loop body is not executed at all, but no error is
returned, as shown by the following example:
BEGIN
FOR i IN 10 .. 1 LOOP
DBMS_OUTPUT.PUT_LINE('Iteration # ' || i);
END LOOP;
END;
This example generates no output, because the loop body is never executed.
The following example uses the REVERSE keyword:
BEGIN
FOR i IN REVERSE 1 .. 10 LOOP
DBMS_OUTPUT.PUT_LINE('Iteration # ' || i);
END LOOP;
END;
Iteration # 10
Iteration # 9
Iteration # 8
Iteration # 7
Iteration # 6
Iteration # 5
Iteration # 4
Iteration # 3
Iteration # 2
Iteration # 1
Invocation
This statement can only be specified in a PL/SQL block.
Authorization
The privileges held by the authorization ID of the statement must include all of the privileges necessary to
invoke the data change statement that is specified in the FORALL statement.
INDICES OF indexing-array
VALUES OF indexing-array
insert-statement
searched-delete-statement
searched-update-statement
execute-immediate-statement
Description
index-variable
Identifies a name to be used as an array index. It is implicitly declared as an INTEGER and it can only
be referenced in the FORALL statement.
lower-bound .. upper-bound
Identifies a range of index values that are assignable to the index-variable with lower-bound less than
upper-bound. The range represents every integer value starting with lower-bound and incrementing
by 1 up to and including upper-bound.
INDICES OF indexing-array
Identifies the set of array index values of the array identified by indexing-array. If indexing-array is an
associative array, array index values must be assignable to index-variable and could be a sparse set.
VALUES OF indexing-array
Identifies the set of element values of the array identified by indexing-array. The element values must
be assignable to index-variable and could be an unordered sparse set.
insert-statement
Specifies an INSERT statement that is effectively executed for each index-variable value.
searched-delete-statement
Specifies a searched DELETE statement that is effectively executed for each index-variable value.
searched-update-statement
Specifies a searched UPDATE statement that is effectively executed for each index-variable value.
execute-immediate-statement
Specifies an EXECUTE IMMEDIATE statement that is effectively executed for each index-variable
value.
Notes
• FORALL statement processing is not atomic. If an error occurs while iterating in the FORALL statement,
any data change operations that have already been processed are not implicitly rolled back. An
application can use a ROLLBACK statement to roll back the entire transaction when an error occurs in
the FORALL statement.
Example
The following example shows a basic FORALL statement:
FORALL x
IN in_customer_list.FIRST..in_customer_list.LAST
DELETE FROM customer
WHERE cust_id IN in_customer_list(x);
Invocation
This statement can be embedded within a FOR, LOOP, or WHILE statement in a PL/SQL procedure,
function, or anonymous block.
Authorization
No privileges are required to invoke the EXIT statement. However, the authorization ID of the statement
must hold the necessary privileges to invoke the SQL statements that are embedded within the FOR,
LOOP, or WHILE statement.
Syntax
EXIT
Example
The following example shows a basic LOOP statement with an EXIT statement within an anonymous
block:
DECLARE
sum PLS_INTEGER := 0;
BEGIN
LOOP
sum := sum + 1;
IF sum > 10 THEN
EXIT;
END IF;
END LOOP;
END
Invocation
This statement can be embedded in a PL/SQL procedure, function, or anonymous block statement.
Authorization
No privileges are required to invoke the LOOP statement. However, the authorization ID of the statement
must hold the necessary privileges to invoke the SQL statements that are embedded within the LOOP
statement.
Syntax
LOOP statements END LOOP
Description
statements
Specifies one or more PL/SQL or SQL statements. These statements are executed during each
iteration of the loop.
Example
The following example shows a basic LOOP statement within an anonymous block:
Invocation
This statement can be embedded within a PL/SQL procedure, function, or anonymous block statement.
Authorization
No privileges are required to invoke the WHILE statement; however, the authorization ID of the statement
must hold the necessary privileges to invoke the SQL statements that are embedded in the WHILE
statement.
Syntax
WHILE expression LOOP statements END LOOP
Description
expression
Specifies an expression that is evaluated immediately before each entry into the loop body to
determine whether or not the loop is to be executed. If the expression is logically true, the loop is
executed. If the expression is logically false, loop processing ends. An EXIT statement can be used to
terminate the loop while the expression is true.
statements
Specifies the PL/SQL and SQL statements that are executed each time that the loop is processed.
Example
The following example shows a basic WHILE statement within an anonymous block:
DECLARE
sum INTEGER := 0;
BEGIN
WHILE sum < 11 LOOP
sum := sum + 1;
END LOOP;
END
The WHILE statement within this anonymous block executes until sum is equal to 11; loop processing
then ends, and processing of the anonymous block proceeds to completion.
Invocation
This statement can be embedded within a FOR, LOOP, or WHILE statement, or within a PL/SQL procedure,
function, or anonymous block statement.
Syntax
CONTINUE
Example
The following example shows a basic LOOP statement with an CONTINUE statement within an
anonymous block:
BEGIN
FOR i IN 1 .. 5 LOOP
IF i = 3 THEN
CONTINUE;
END IF;
DBMS_OUTPUT.PUT_LINE('Iteration # ' || i);
END LOOP;
END;
Iteration # 1
Iteration # 2
Iteration # 4
Iteration # 5
Syntax
BEGIN
statement
DECLARE declaration
END
If no error occurs, the block simply executes statement, and control passes to the statement after END.
However, if an error occurs while executing a statement, further processing of the statement is
abandoned, and control passes to the EXCEPTION section. The WHEN clauses are searched for the first
exception matching the error that occurred. If a match is found, the corresponding handler-statement is
executed, and control passes to the statement after END. If no match is found, the program stops
executing.
If a new error occurs during execution of the handler-statement, it can only be caught by a surrounding
EXCEPTION clause.
DECLARE
exception1 EXCEPTION;
exception2 EXCEPTION;
PRAGMA EXCEPTION_INIT(exception2,-942);
exception3 EXCEPTION;
PRAGMA DB2_EXCEPTION_INIT(exception3,'42601');
BEGIN
MyApp.Main(100);
EXCEPTION
WHEN exception1 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception1 caught');
WHEN exception2 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception2 (Undefined name) caught');
WHEN exception3 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception3 (Syntax error) caught');
END
Note: A limited number of Oracle sqlcodes are accepted by the Db2 data server as arguments to PRAGMA
EXCEPTION_INIT. Refer to “Oracle-Db2 error mapping (PL/SQL)” on page 68 for the full list.
When an exception initialized with PRAGMA EXCEPTION_INIT is caught, the value returned by the
SQLCODE function is the sqlcode associated with the exception, not the Oracle value. In the previous
example, when exception2 is caught, the value returned by SQLCODE will be -204, which is the sqlcode
corresponding to Oracle sqlcode -942. If the Oracle sqlcode specified in PRAGMA EXCEPTION_INIT is
not listed in the Oracle-Db2 error mapping table, then compilation fails. You can avoid this by replacing
PRAGMA EXCEPTION_INIT with PRAGMA DB2_EXCEPTION_INIT and specifying the Db2 sqlstate
corresponding to the error that you want identified.
Table 5 on page 65 summarizes the built-in exceptions that you can use. The special exception name
OTHERS matches every exception. Condition names are not case sensitive.
Syntax
RAISE_APPLICATION_ERROR ( error-number , message ,
) ;
false
keeperrorstack
Description
error-number
A vendor-specific number that is mapped to an error code before it is stored in a variable named
SQLCODE. The RAISE_APPLICATION_ERROR procedure accepts user-defined error-number values
from -20000 to -20999. The SQLCODE that is returned in the error message is SQL0438N. The
SQLSTATE contains class 'UD' plus three characters that correspond to the last three digits of the
error-number value.
message
A user-defined message with a maximum length of 70 bytes.
keeperrorstack
An optional boolean value indicating whether the error stack should be preserved. Currently, only the
default value of false is supported.
Example
The following example uses the RAISE_APPLICATION_ERROR procedure to display error codes and
messages that are specific to missing employee information:
CALL verify_emp(7839);
SQLCODE: -438
SQLERRM: SQL0438N Application raised error or warning with
diagnostic text: "No manager for 7839". SQLSTATE=UD030
Syntax
RAISE exception
Description
exception
Specifies a previously-defined exception.
Example
The following example shows a procedure that raises an exception of oddno or evenno based on the
value provided as argument in the invocation::
SET SERVEROUTPUT ON
/
Return Status = 0
Table 6. Mapping of PL/SQL error codes and exception names to Db2 data server error codes and
SQLSTATE values
plsqlCode plsqlName db2Code db2State
-1 DUP_VAL_ON_INDEX -803 23505
+100 NO_DATA_FOUND +100 02000
-1012 NOT_LOGGED_ON -1024 08003
-1017 LOGIN_DENIED -30082 08001
-1476 ZERO_DIVIDE -801 22012
-1722 INVALID_NUMBER -420 22018
-1001 INVALID_CURSOR -501 24501
-1422 TOO_MANY_ROWS -811 21000
-6502 VALUE_ERROR -433 22001
-6511 CURSOR_ALREADY_OPEN -502 24502
-6532 SUBSCRIPT_OUTSIDE_LIMIT -20439 428H1
-6533 SUBSCRIPT_BEYOND_COUNT -20439 2202E
-6592 CASE_NOT_FOUND -773 20000
-54 -904 57011
-60 -911 40001
-310 -206 42703
-595 -390 42887
-597 -303 42806
-598 -407 23502
-600 -30071 58015
-603 -119 42803
-604 -119 42803
-610 -20500 428HR
-611 -117 42802
-612 -117 42802
-613 -811 21000
-615 -420 22018
-616 -420 22018
-617 -418 42610
Cursors (PL/SQL)
A cursor is a named control structure used by an application program to point to and select a row of data
from a result set. Instead of executing a query all at once, you can use a cursor to read and process the
query result set one row at a time.
A cursor in a PL/SQL context is treated as a WITH HOLD cursor. For more information about WITH HOLD
cursors, see "DECLARE CURSOR statement".
The Db2 data server supports both PL/SQL static cursors and cursor variables.
Syntax
CURSOR cursor-name IS query
Description
cursor-name
Specifies an identifier for the cursor that can be used to reference the cursor and its result set.
query
Specifies a SELECT statement that determines a result set for the cursor.
Example
The following example shows a procedure that contains multiple static cursor declarations:
If 2000 is passed in as the value of max_wage, only the name and salary data for those employees whose
salary is less than 2000 is returned:
Parameterized cursors can only reference its own parameters. Parameterized cursors cannot reference
local variables. In this example, cursor_id must be used in the select statement because in_id is not
within the scope of the cursor.
BEGIN
FOR r IN c(in_id) LOOP
empName := r.emp_name;
DBMS_OUTPUT.PUT_LINE(empName);
END LOOP;
END;
Syntax
OPEN cursor-name
,
( expression )
expression
Description
cursor-name
Specifies an identifier for a cursor that was previously declared within a PL/SQL context. The specified
cursor cannot already be open.
expression
When cursor-name is a parameterized cursor, specifies one or more optional actual parameters. The
number of actual parameters must match the number of corresponding formal parameters.
Syntax
FETCH cursor-name INTO record
,
variable
bulk-collect-clause
bulk-collect-clause
,
Description
cursor-name
Name of a static cursor or cursor variable.
record
Identifier for a previously-defined record. This can be a user-defined record or a record definition that
is derived from a table using the %ROWTYPE attribute.
variable
A PL/SQL variable that will hold the field data from the fetched row. One or more variables can be
defined, but they must match in order and number the fields that are returned in the select list of the
query that was specified in the cursor declaration. The data types of the fields in the select list must
match or be implicitly convertible to the data types of the fields in the record or the data types of the
variables.
The variable data types can be defined explicitly or by using the %TYPE attribute.
BULK COLLECT INTO array-variable
Identifies one or more variables with an array data type. Each row of the result is assigned to an
element in each array in the order of the result set, with the array index assigned in sequence.
• If exactly one array-variable is specified:
– If the data type of the array-variable element is not a record type, the result row of the cursor
must have exactly one column, and the column data type must be assignable to the array
element data type.
– If the data type of the array-variable element is a record type, the result row of the cursor must
be assignable to the record type.
Example
The following example shows a procedure that contains a FETCH statement.
If the %TYPE attribute is used to define the data type of a target variable, the target variable declaration
in a PL/SQL application program does not need to change if the data type of the database column
changes. The following example shows a procedure with variables that are defined using the %TYPE
attribute.
If all of the columns in a table are retrieved in the order in which they are defined, the %ROWTYPE
attribute can be used to define a record into which the FETCH statement will place the retrieved data.
Each field within the record can then be accessed using dot notation. The following example shows a
procedure with a record definition that uses %ROWTYPE. This record is used as the target of the FETCH
statement.
Syntax
CLOSE cursor-name
Description
cursor-name
Specifies an identifier for an open cursor that was previously declared within a PL/SQL context.
Example
The following example shows a CLOSE statement for a cursor that is part of the CURSOR_EXAMPLE
procedure:
A call to this procedure (CALL emp_info;) returns the following sample output:
Syntax
DECLARE cursor-variable-name SYS_REFCURSOR
Description
cursor-variable-name
Specifies an identifier for the cursor variable.
SYS_REFCURSOR
Specifies that the data type of the cursor variable is the built-in SYS_REFCURSOR data type.
Example
The following example shows a SYS_REFCURSOR variable declaration:
Syntax
TYPE cursor-type-name IS REF CURSOR
RETURN return-type
Description
TYPE cursor-type-name
Specifies an identifier for the cursor data type.
IS REF CURSOR
Specifies that the cursor is of a user-defined REF CURSOR data type.
RETURN return-type
Specifies the return type that is associated with the cursor. If a return-type is specified, this REF
CURSOR type is strongly typed; otherwise, it is weakly typed.
Example
The following example shows a cursor variable declaration in a package:
Syntax
OPEN cursor-variable-name FOR dynamic-string
USING bind-arg
Description
OPEN cursor-variable-name
Specifies an identifier for a cursor variable that was previously declared within a PL/SQL context.
FOR dynamic-string
Specifies a string literal or string variable that contains a SELECT statement (without the terminating
semicolon). The statement can contain named parameters, such as, for example, :param1.
USING bind-arg
Specifies one or more bind arguments whose values are substituted for placeholders in dynamic-
string when the cursor opens.
Examples
The following example shows a dynamic query that uses a string literal:
CALL dept_query;
EMPNO ENAME
----- -------
7499 ALLEN
7698 BLAKE
7844 TURNER
The query in the previous example can be modified with bind arguments to pass the query parameters:
The following CALL statement generates the same output that was generated in the previous example:
A string variable to pass the SELECT statement provides the most flexibility:
This version of the DEPT_QUERY procedure generates the following example output:
EMPNO ENAME
----- -------
7566 JONES
7788 SCOTT
7902 FORD
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_job emp.job%TYPE := 'SALESMAN';
v_emp_refcur SYS_REFCURSOR;
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPLOYEES WITH JOB ' || v_job);
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
emp_by_job(v_job, v_emp_refcur);
LOOP
FETCH v_emp_refcur INTO v_empno, v_ename;
EXIT WHEN v_emp_refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_ename);
END LOOP;
CLOSE v_emp_refcur;
END;
The following example output is generated when the anonymous block executes:
In the next example, a procedure opens a cursor variable whose query retrieves all rows for a given
department:
The following example shows a procedure that opens a cursor variable whose query retrieves all rows in
the DEPT table:
The following example shows a procedure that fetches and displays a cursor variable result set consisting
of department number and name:
The following example shows an anonymous block that executes these procedures:
DECLARE
gen_refcur SYS_REFCURSOR;
BEGIN
DBMS_OUTPUT.PUT_LINE('ALL EMPLOYEES');
open_all_emp(gen_refcur);
fetch_emp(gen_refcur);
DBMS_OUTPUT.PUT_LINE('****************');
DBMS_OUTPUT.PUT_LINE('DEPARTMENTS');
open_dept(gen_refcur);
fetch_dept(gen_refcur);
DBMS_OUTPUT.PUT_LINE('*****************');
close_refcur(gen_refcur);
END;
The following example output is generated when the anonymous block executes:
ALL EMPLOYEES
EMPNO ENAME
----- -------
Triggers (PL/SQL)
A PL/SQL trigger is a named database object that encapsulates and defines a set of actions that are to be
performed in response to an insert, update, or delete operation against a table. Triggers are created using
the PL/SQL CREATE TRIGGER statement.
INSERTING
UPDATING
DELETING
True if the trigger was activated by a delete operation. False otherwise.
INSERTING
True if the trigger was activated by an insert operation. False otherwise.
UPDATING
True if the trigger was activated by an update operation. False otherwise.
These predicates can be specified as a single search condition, or as a boolean factor within a complex
search condition in a WHEN clause or PL/SQL statement.
Syntax
CREATE TRIGGER trigger-name BEFORE
OR REPLACE AFTER
INSTEAD OF
trigger-event ON table-name
AS
1
REFERENCING OLD correlation-name
AS
NEW correlation-name
BEGIN statement
DECLARE declaration
END
trigger-event
OR
2
INSERT
DELETE
UPDATE
,
OF column-name
Notes:
1OLD and NEW can only be specified once each.
2A trigger event must not be specified more than once for the same operation. For example, INSERT
OR DELETE is allowed, but INSERT OR INSERT is not allowed.
Example
The following example shows a before row-level trigger that calculates the commission of every new
employee belonging to department 30 before a record for that employee is inserted into the EMP table. It
also records any salary increases that exceed 50% in an exception table:
Syntax
DROP TRIGGER trigger-name
Description
trigger-name
Specifies the name of the trigger that is to be dropped.
The trigger computes the commissions for two new employees and inserts those values as part of the
new employee rows:
In the following example, two employee rows are added using two separate INSERT statements, and then
both rows are updated using a single UPDATE statement. The JOBHIST table shows the action of the
trigger for each affected row: two new hire entries for the two new employees and two changed
UPDATE emp SET comm = sal * 1.1 WHERE empno IN (9003, 9004);
CHG_DATE CHG_DESC
--------- ------------------------------
31-MAR-05 Added employee # 9003
31-MAR-05 Added employee # 9004
31-MAR-05 Updated employee # 9003
31-MAR-05 Updated employee # 9004
After both employees are deleted with a single DELETE statement, the EMPCHGLOG table shows that the
trigger was fired twice, once for each deleted employee:
CHG_DATE CHG_DESC
--------- ------------------------------
31-MAR-05 Added employee # 9003
31-MAR-05 Added employee # 9004
31-MAR-05 Updated employee # 9003
31-MAR-05 Updated employee # 9004
31-MAR-05 Deleted employee # 9003
31-MAR-05 Deleted employee # 9004
Packages (PL/SQL)
PL/SQL package definitions are supported by the Db2 data server. A PL/SQL package is a named
collection of functions, procedures, variables, cursors, user-defined types, and records that are
referenced using a common qualifier, the package name.
Packages have the following characteristics:
• Packages provide a convenient way of organizing the functions and procedures that have a related
purpose. Permission to use the package functions and procedures is dependent upon one privilege that
is granted to the entire package.
• Certain items in a package can be declared public. Public entities are visible and can be referenced by
other programs that hold the EXECUTE privilege on the package. In the case of public functions and
procedures, only their signatures are visible. The PL/SQL code for these function and procedures is not
accessible to others; therefore, applications that utilize such a package are dependent upon only the
information that is available in the signatures.
• Other items in a package can be declared private. Private entities can be referenced and used by
functions and procedures within the package, but not by external applications.
FUNCTION get_dept_name (
p_deptno NUMBER DEFAULT 10
)
RETURN VARCHAR2;
FUNCTION update_emp_sal (
p_empno NUMBER,
p_raise NUMBER
)
RETURN NUMBER;
PROCEDURE hire_emp (
p_empno NUMBER,
p_ename VARCHAR2,
p_job VARCHAR2,
p_sal NUMBER,
p_hiredate DATE DEFAULT sysdate,
p_comm NUMBER DEFAULT 0,
p_mgr NUMBER,
p_deptno NUMBER DEFAULT 10
);
PROCEDURE fire_emp (
p_empno NUMBER
);
END emp_admin;
Attention:
When you use CREATE or REPLACE syntax for package specification of package whose body was
created by a CREATE PACKAGE BODY statement, the existing package body is dropped and needs
to be re-created before any of package objects are invoked.
Syntax
CREATE PACKAGE package-name IS
OR REPLACE AS
declaration
PROCEDURE procedure-name
,
( )
procedure-parameter
( )
function-parameter
END package-name
Description
package-name
Specifies an identifier for the package.
declaration
Specifies an identifier for a public item. The public item can be accessed from outside of the package
using the syntax package-name.item-name. There can be zero or more public items. Public item
declarations must come before procedure or function declarations. The declaration can be any of the
following:
• Collection declaration
• EXCEPTION declaration
• Record declaration
• REF CURSOR and cursor variable declaration
• TYPE definition for a collection, record, or REF CURSOR type variable
• SUBTYPE definition
• Variable declaration
procedure-name
Specifies an identifier for a public procedure. The public procedure can be invoked from outside of the
package using the syntax package-name.procedure-name().
procedure-parameter
Specifies an identifier for a formal parameter of the procedure.
function-name
Specifies an identifier for a public function. The public function can be invoked from outside of the
package using the syntax package-name.function-name().
Notes
The CREATE PACKAGE statement can be submitted in obfuscated form. In an obfuscated statement, only
the package name is readable. The rest of the statement is encoded in such a way that it is not readable,
but can be decoded by the database server. Obfuscated statements can be produced by calling the
DBMS_DDL.WRAP function.
--
-- Package body for the 'emp_admin' package.
--
CREATE OR REPLACE PACKAGE BODY emp_admin
IS
--
-- Function that queries the 'dept' table based on the department
-- number and returns the corresponding department name.
--
FUNCTION get_dept_name (
p_deptno IN NUMBER DEFAULT 10
)
RETURN VARCHAR2
IS
v_dname VARCHAR2(14);
BEGIN
SELECT dname INTO v_dname FROM dept WHERE deptno = p_deptno;
RETURN v_dname;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Invalid department number ' || p_deptno);
RETURN '';
END;
--
-- Function that updates an employee's salary based on the
-- employee number and salary increment/decrement passed
-- as IN parameters. Upon successful completion the function
-- returns the new updated salary.
--
FUNCTION update_emp_sal (
p_empno IN NUMBER,
p_raise IN NUMBER
)
RETURN NUMBER
IS
v_sal NUMBER := 0;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = p_empno;
v_sal := v_sal + p_raise;
UPDATE emp SET sal = v_sal WHERE empno = p_empno;
RETURN v_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee ' || p_empno || ' not found');
RETURN -1;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('The following is SQLERRM:');
DBMS_OUTPUT.PUT_LINE(SQLERRM);
DBMS_OUTPUT.PUT_LINE('The following is SQLCODE:');
DBMS_OUTPUT.PUT_LINE(SQLCODE);
RETURN -1;
END;
--
-- Procedure that inserts a new employee record into the 'emp' table.
--
PROCEDURE hire_emp (
Syntax
CREATE PACKAGE BODY package-name IS
OR REPLACE AS
private-declaration procedure-specification
function-specification
END
BEGIN initialization-statement
procedure-specification
( parameter )
BEGIN statement
procedure-declaration
END
function-specification
FUNCTION function-name RETURN
,
( parameter )
AS function-declaration
END
Description
package-name
Specifies the name of the package whose body is to be created. A package specification with the
same name must exist.
private-declaration
Specifies the name of a private object that can be accessed by any procedure or function within the
package. There can be zero or more private variables. The private-declaration can be any of the
following:
• Variable declaration
• Record declaration
• Collection declaration
• REF CURSOR and cursor variable declaration
• TYPE definitions for records, collections, or variables of the REF CURSOR type
• SUBTYPE definition over a base type
procedure-name
Specifies the name of a public procedure that is declared in the package specification and its
signature. The signature can specify any one of the following: the formal parameter names, data
types, parameter modes, the order of the formal parameters, or the number of formal parameters.
Notes
The CREATE PACKAGE BODY statement can be submitted in obfuscated form. In an obfuscated
statement, only the package name is readable. The rest of the statement is encoded in such a way that it
is not readable, but can be decoded by the database server. Obfuscated statements can be produced by
calling the DBMS_DDL.WRAP function.
package_name.type_name
package_name.item_name
package_name.subprogram_name
schema.package_name.subprogram_name
Example
The following example contains a reference to a function named GET_DEPT_NAME that is defined in a
package named EMP_ADMIN:
FUNCTION get_dept_name (
p_deptno IN dept_num
) RETURN VARCHAR2;
FUNCTION open_emp_by_dept (
p_deptno IN dept_num
) RETURN EMP_REFCUR;
PROCEDURE fetch_emp (
p_refcur IN OUT SYS_REFCURSOR
);
PROCEDURE close_refcur (
p_refcur IN OUT SYS_REFCURSOR
);
END emp_rpt;
The definition of the associated package body includes the following private variable declarations:
• A static cursor, DEPT_CUR
• An associative array type, DEPTTAB_TYP
• An associative array variable, T_DEPT
• An integer variable, T_DEPT_MAX
• A record variable, R_EMP
FUNCTION get_dept_name (
p_deptno IN dept_num
) RETURN VARCHAR2
IS
BEGIN
FOR i IN 1..t_dept_max LOOP
IF p_deptno = t_dept(i).deptno THEN
RETURN t_dept(i).dname;
END IF;
END LOOP;
RETURN 'Unknown';
END;
PROCEDURE fetch_emp (
p_refcur IN OUT SYS_REFCURSOR
)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH p_refcur INTO r_emp;
EXIT WHEN p_refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(r_emp.empno || ' ' || r_emp.ename);
END LOOP;
END;
PROCEDURE close_refcur (
p_refcur IN OUT SYS_REFCURSOR
)
IS
BEGIN
CLOSE p_refcur;
END;
BEGIN
OPEN dept_cur;
LOOP
FETCH dept_cur INTO t_dept(t_dept_max);
EXIT WHEN dept_cur%NOTFOUND;
t_dept_max := t_dept_max + 1;
END LOOP;
CLOSE dept_cur;
t_dept_max := t_dept_max - 1;
END emp_rpt;
This package contains an initialization section that loads the private associative array variable T_DEPT,
using the private static cursor DEPT_CUR. T_DEPT serves as a department name lookup table in function
GET_DEPT_NAME. The function OPEN_EMP_BY_DEPT returns a REF CURSOR variable for the result set of
employee numbers and names for a given department. This REF CURSOR variable can then be passed to
procedure FETCH_EMP to retrieve and list the individual rows of the result set. Finally, procedure
CLOSE_REFCUR can be used to close the REF CURSOR variable that is associated with this result set.
The following anonymous block runs the package functions and procedures. The declaration section
includes the declaration of a scalar variable V_DEPTNO, using the public SUBTYPE DEPT_NUM and a
cursor variable V_EMP_CUR, using the public REF CURSOR type, EMP_REFCUR. V_EMP_CUR contains a
pointer to the result set that is passed between the package function and procedures.
DECLARE
v_deptno emp_rpt.DEPT_NUM DEFAULT 30;
v_emp_cur emp_rpt.EMP_REFCUR;
BEGIN
v_emp_cur := emp_rpt.open_emp_by_dept(v_deptno);
DBMS_OUTPUT.PUT_LINE('EMPLOYEES IN DEPT #' || v_deptno ||
': ' || emp_rpt.get_dept_name(v_deptno));
emp_rpt.fetch_emp(v_emp_cur);
DBMS_OUTPUT.PUT_LINE('**********************');
DBMS_OUTPUT.PUT_LINE(v_emp_cur%ROWCOUNT || ' rows were retrieved');
emp_rpt.close_refcur(v_emp_cur);
END;
The following anonymous block shows another way of achieving the same result. Instead of using the
package procedures FETCH_EMP and CLOSE_REFCUR, the logic is coded directly into the anonymous
block. Note the declaration of record variable R_EMP, using the public record type EMPREC_TYP.
DECLARE
v_deptno emp_rpt.DEPT_NUM DEFAULT 30;
v_emp_cur emp_rpt.EMP_REFCUR;
r_emp emp_rpt.EMPREC_TYP;
BEGIN
v_emp_cur := emp_rpt.open_emp_by_dept(v_deptno);
DBMS_OUTPUT.PUT_LINE('EMPLOYEES IN DEPT #' || v_deptno ||
': ' || emp_rpt.get_dept_name(v_deptno));
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH v_emp_cur INTO r_emp;
EXIT WHEN v_emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(r_emp.empno || ' ' ||
r_emp.ename);
END LOOP;
DBMS_OUTPUT.PUT_LINE('**********************');
DBMS_OUTPUT.PUT_LINE(v_emp_cur%ROWCOUNT || ' rows were retrieved');
CLOSE v_emp_cur;
END;
Syntax
DROP PACKAGE package-name
BODY
Description
BODY
Specifies that only the package body is to be dropped. If this keyword is omitted, both the package
specification and the package body are dropped.
package-name
Specifies the name of a package.
Examples
The following example shows how to drop only the body of a package named EMP_ADMIN:
B D
blocks data types
PL/SQL 11 PL/SQL 24, 36, 41
BULK COLLECT INTO clause 47 REF CURSOR 76
C E
CASE statement errors
PL/SQL 55 Db2-dashDB mapping 68
searched 57 Db2-Oracle mapping 68
simple 55 mapping 68
CLOSE statement PL/SQL applications 66
closing cursors 74 examples
collections PL/SQL schema 4
associative arrays 25 PL/SQL triggers 86
methods 29 exceptions
overview 20 PL/SQL
VARRAY type 20 handling 64
CONTINUE statement 63 transactions 82
control statements EXECUTE IMMEDIATE statement
PL/SQL PL/SQL 44
CONTINUE 63 EXIT statement 62
EXIT 62
list 51
LOOP 62
F
CREATE FUNCTION statement FETCH statement
PL/SQL 17 PL/SQL 72
CREATE PACKAGE BODY statement 92 FOR (cursor variant) statement 58
CREATE PACKAGE statement 90 FOR (integer variant) statement 59
CREATE PROCEDURE statement FORALL statement
PL/SQL 13 PL/SQL 60
CREATE TRIGGER statement 83 FOUND cursor attribute 75
CREATE TYPE (Nested table) statement functions
PL/SQL 23 invocation syntax support in PL/SQL 16
CREATE TYPE (Object) statement parameter modes 35
PL/SQL 24 PL/SQL
CREATE TYPE (VARRAY) statement
Index 99
functions (continued) PL/SQL (continued)
PL/SQL (continued) collections (continued)
overview 17 overview 20
references 20 VARRAY type 20
control statements
CONTINUE 63
I EXIT 62
IF statement FOR (cursor variant) 58
PL/SQL 51 FOR (integer variant) 59
ISOPEN attribute 75 FORALL 60
LOOP 62
overview 51
L WHILE 63
cursor variables
LOOP statement
opening 77
PL/SQL 62
overview 76
loops
ROWTYPE attribute 74
PL/SQL 58
SYS_REFCURSOR built-in data type 76
cursors
M attributes 75
closing 74
methods declaring 70
collection 29 fetching rows from 72
opening 71
N overview 70
parameterized 70
NEW trigger variable 81 data types
NOTFOUND attribute 75 list 36
NULL record 24, 41
statement 43 subtype 41
dynamic queries 77
exception handling 64
O function invocation syntax support 16
obfuscation functions
PL/SQL 10 creating 3
SQL PL 10 overview 17
objects references to 20
packages 94 loops 58
OLD trigger variable 81 modularizing cursor operations example 79
OPEN FOR statement 77 obfuscation 10
OPEN statement overview 1
PL/SQL 71 packages
components 88
creating 89
P creating body 91
creating package specifications 89
packages dropping 97
bodies 91 overview 88
objects 94 referencing objects 94
PL/SQL specifications 90
components 88 user-defined types 95
creating 89 parameters
creating package bodies 91, 92 %TYPE attribute 39
creating package specifications 89 procedures
dropping 97 creating 3
overview 88 overview 13
user-defined types 95 references to 15
parameter modes 35 raising exceptions 66
parameterized cursors 70 REF CURSOR data type
PL/SQL details 76
blocks 11 example 78
collection methods 29 restrictions 4
collections sample schema 4
associative arrays 25 statement attributes 51
Index 101
triggers (continued)
PL/SQL
commits 82
creating 83
dropping 86
examples 86
overview 81
rollbacks 82
row-level 81
trigger event predicates 82
trigger variables 81
TYPE attribute 39
U
UDTs
PL/SQL packages 95
V
variables
cursor data types 76
PL/SQL
declaring 33
overview 33
record 24
REF CURSOR 76
trigger 81
VARRAY collection type 20