Chapter 2. Basic SQL Procedure Structure

In this chapter, you will learn

  • The fundamental structure of an SQL procedure

  • The various clauses for the CREATE PROCEDURE statement

  • The structure of the procedure body

  • The statements that can be coded in the procedure body

Stored procedures are used to encapsulate multiple SQL statements with flow logic. They are database objects that serve as sub-routines to applications. SQL procedures are defined in a database using the CREATE PROCEDURE statement. This chapter introduces the syntax of the CREATE PROCEDURE statement and uses examples to illustrate how to create simple SQL procedures.

The CREATE PROCEDURE Statement

The CREATE PROCEDURE statement defines a procedure in the database. The clauses define the name and parameters as well as the procedure body consisting of one or more SQL PL statements. Figure 2.1 describes the syntax of the CREATE PROCEDURE statement and the clauses that apply to SQL procedures.

Example 2.1. CREATE PROCEDURE statement syntax for DB2 UDB LUW.

>>-CREATE PROCEDURE--procedure-name----------------------------->


>--+----------------------------------------------------+--*---->
   '-(--+------------------------------------------+--)-'
        | .-,------------------------------------. |
        | V .-IN----.                            | |
        '---+-------+--parameter-name--data-type-+-'
            +-OUT---+
            '-INOUT-'


>--+--------------------------+--*------------------------------->
   '-SPECIFIC--specific-name--'


   .-DYNAMIC RESULT SETS 0--------.     .-MODIFIES SQL DATA-.
>--+------------------------------+--*--+-------------------+--->
   '-DYNAMIC RESULT SETS--integer-'     +-CONTAINS SQL------+
                                        '-READS SQL DATA----'



      .-NOT DETERMINISTIC-.     .-CALLED ON NULL INPUT-.
>--*--+-------------------+--*--+----------------------+--*----->
      '-DETERMINISTIC-----'



   .-INHERIT SPECIAL REGISTERS-.     .-OLD SAVEPOINT LEVEL-.
>--+---------------------------+--*--+---------------------+---->
                                     '-NEW SAVEPOINT LEVEL-'



      .-LANGUAGE SQL-.     .-EXTERNAL ACTION----.
>--*--+--------------+--*--+--------------------+--*------------>
                           '-NO EXTERNAL ACTION-'


>--+------------------------------+--*-------------------------->
   '-PARAMETER CCSID--+-ASCII---+-'
                      '-UNICODE-'


>--| SQL-procedure-body |--------------------------------------><



SQL-procedure-body:


|---SQL-procedure-statement-------------------------------------|

When you issue the CREATE PROCEDURE statement, DB2 defines the procedure in the database and makes entries in the catalog tables to record the existence of the procedure.

Procedure Name

The procedure name specifies the procedure being defined. The name is an SQL identifier that can be a maximum of 128 characters. It must begin with a letter and may be followed by additional letters, digits, or the underscore character “_”.

These are examples of valid procedure names:

UPDATE_EMPLOYEE_SALARY
READEMP

These examples are of unqualified procedure names. When a procedure name is unqualified, the procedure schema is determined by the CURRENT SCHEMA special register. The DB2 special register will be discussed later in this chapter. By default, the CURRENT SCHEMA is the authorization ID of the current user. Procedure names may also be qualified by a schema name explicitly. These are examples of valid qualified procedure names:

HRAPP.UPDATE_EMPLOYEE_SALARY
DB2ADMIN.READEMP

Similar to the procedure name, the schema name is an SQL identifier with a maximum of 128 characters or 10 characters on iSeries. The schema name cannot begin with SYS.

The qualified procedure name does not necessarily need to be unique in the database. The combination of qualified procedure name and number of parameters (procedure signature), however, must uniquely identify a procedure. This topic will be discussed in more detail in the following section.

The SPECIFIC clause is important when there is a requirement to define procedures with the same name but with a different number of parameters. To fully understand the purpose of this clause, we must discuss parameters.

Parameters

The parameters for a procedure are defined in the CREATE PROCEDURE statement. The definition of each parameter consists of three parts:

  • Modedefines whether the parameter is an input (IN), output (OUT), or both (INOUT).

  • Parameter namespecifies the name of the parameter. It is recommended that all parameter variables be prefixed with p_. This is discussed in detail in the “Variables” section of this chapter.

  • Data typeis the SQL data type and size, if applicable, for this parameter.

The list of parameters is enclosed in parentheses “( )”, and each parameter definition is delimited by a comma “,”.

Figure 2.2 is an example of a partial CREATE PROCEDURE statement that defines the procedure and its parameters.

Example 2.2. Defining procedure parameters.

CREATE PROCEDURE update_employee_salary ( IN  P_EMPID INTEGER
                                        , IN  P_PERCENTINCR DECIMAL(4,2)
                                        , INOUT P_EMPCOUNT INTEGER
                                        , OUT P_UPDATED_SALARY DECIMAL(5,2))
. . .

A procedure may be defined without any parameters, and the parentheses can be omitted, as in this example:

CREATE PROCEDURE increase_salary LANGUAGE SQL BEGIN . . .

To allow back-level DB2 support, parentheses may be coded in the CREATE PROCEDURE statement.

CREATE PROCEDURE increase_salary() LANGUAGE SQL BEGIN . . .

On LUW and iSeries, it is possible to define multiple procedures with the same qualified name but different numbers of parameters. This is called overloading, and the procedures are referred to as overloaded procedures. Figures 2.3 and 2.4 show examples of overloaded procedures. zSeries does not support overloaded procedures. Therefore, examples run in zSeries have to be created with different procedure names.

Example 2.3. Procedure sum with three parameters.

CREATE PROCEDURE sum( IN  p_a INTEGER
                    , IN  p_b INTEGER
                    , OUT p_s INTEGER)
    LANGUAGE SQL
    SPECIFIC sum_ab                             -- applies to LUW and iSeries
 -- WLM ENVIRONMENT <env>                       -- applies to zSeries
BEGIN
    SET p_s = p_a + p_b;
END

Example 2.4. Procedure sum with four parameters.

CREATE PROCEDURE sum( IN  p_a INTEGER
                    , IN  p_b INTEGER
                    , IN  p_c INTEGER
                    , OUT p_s INTEGER)
    LANGUAGE SQL
    SPECIFIC sum_abc                            -- applies to LUW and iSeries
 -- WLM ENVIRONMENT <env>                       -- applies to zSeries
BEGIN
    SET p_s = p_a + p_b + p_c;
END

In the examples, two procedures have the same name, sum. The first procedure has three parameters, and the second has four parameters. When sum is called, DB2 determines which version of the procedure to execute based on the number of parameters. Note that each procedure is defined with a unique specific name. Specific names will be discussed in the next section.

The following statement can be used to invoke the SQL procedure:

CALL sum(100,200,?)

This call results in the sum procedure in Figure 2.3 to be executed because there are three parameters. Note that because the third parameter is an output parameter, a “?” must be specified in its place.

Executing the following statement invokes the sum procedure in Figure 2.4 because there are four parameters.

CALL sum(100,200,300,?)

If you attempt to call a procedure where there is no procedure defined in the database with the same number of parameters, an error occurs, as in this example:

CALL sum(100,200,300,400,?)

This call fails because a procedure named sum with five parameters does not exist.

Specific Name

SPECIFIC is an optional clause that defines a unique name for a procedure. Specific names are particularly useful when there are multiple procedures defined with the same name but have a different number of parameters (also known as overloaded procedures, as discussed in the previous section). In this case, each procedure would be given a different specific name which would be used to drop or comment on the stored procedure. Attempting to drop an overloaded procedure using only the procedure name would result in ambiguity and error.

The following example illustrates the use of SPECIFIC name when two procedures with the same name are defined. Consider the two sum procedures defined in Figures 2.3 and 2.4.

To drop the procedure sum, issue the following DROP PROCEDURE statement:

DROP PROCEDURE sum

This statement fails with SQLCODE -476 (SQLSTATE 42725) because the procedure is ambiguous. DB2 cannot determine which of the two procedures called sum should be dropped. To drop a particular version of the sum procedure, you must either specify the procedure parameters with the DROP PROCEDURE statement or use the DROP SPECIFIC PROCEDURE statement. These valid statements drop the procedure:

DROP PROCEDURE sum(INTEGER,INTEGER,INTEGER)
DROP SPECIFIC PROCEDURE sum_ab

By using DROP SPECIFIC PROCEDURE, DB2 knows that it should drop the procedure with the specific name sum_ab. The specific name can also be used with the COMMENT ON statement, as in this example:

COMMENT ON SPECIFIC PROCEDURE sum_abc IS 'THIS IS THE 3 PARM VERSION OF THE
PROCEDURE'

The specific name is an SQL identifier with a maximum length of 18 characters on LUW and 128 characters on iSeries. The name can be unqualified or qualified by a schema name. If it is qualified, it must use the same schema name as the procedure name. The specific name can be the same name as its procedure name. The qualified specific name must be unique among specific procedure names.

In LUW, if the specific name is not explicitly specified when creating a procedure, DB2 generates a unique name for the procedure. The generated unique name consists of SQL and a character timestamp:

SQLyymmddhhmmsshhn

On iSeries, if the specific name is not specified, DB2 uses the procedure name as the specific name. If a procedure already exists with that specific name, a unique name is generated using a portion of the procedure name and a sequence number.

DYNAMIC RESULT SETS

The DYNAMIC RESULT SETS clause specifies the maximum number of result sets you are returning. Handling result sets is explained in detail in Chapter 5, “Understanding and Using Cursors and Result Sets,” and Chapter 8, “Nested SQL Procedures.”

CONTAINS SQL, READS SQL DATA, MODIFIES SQL DATA

The SQL data access indication clause restricts the type of SQL statements that can be executed by the procedure. The default, MODIFIES SQL DATA, is the least restrictive and indicates that any supported SQL statements can be executed.

When CONTAINS SQL is specified, then only statements that do not read or modify data are allowed in the procedure. Examples of such statements are PREPARE, the SET special register, and SQL control statements.

READS SQL DATA can be specified if the procedure contains only statements that do not modify SQL data. Refer to the SQL Reference of the corresponding platform for statements allowed in the SQL procedure for each access indicator.

DETERMINISTIC or NOT DETERMINISTIC

This clause allows you to specify the procedure as DETERMINISTIC if it returns the same results for each invocation of identical input parameters. You can also specify NOT DETERMINISTIC, the default, if the results depend on the input values and/or other values which may change, such as the current date or time. Identifying a procedure as DETERMINISTIC allows DB2 to perform additional optimizations to improve performance because DB2 can just call it once, cache the result, and reuse it.

CALLED ON NULL INPUT

This clause indicates that the procedure will always be called even if its input parameters are null. This behavior is the default, and is the only value that can be specified. This clause is optional and is usually left out.

INHERIT SPECIAL REGISTERS

Special registers are memory registers that allow DB2 to provide information to an application about its environment. Refer to the section “DB2 Special Registers” for more information.

INHERIT SPECIAL REGISTERS is an optional clause and indicates that updateable special registers in the procedure will inherit their initial values from the environment of the invoking statement. Special register inheritance is the default behavior on all platforms.

OLD SAVEPOINT LEVEL, NEW SAVEPOINT LEVEL

This clause is available only in LUW and iSeries. A save point level refers to the scope of reference for any save point related statements. All save point names in the same save point level must be unique.

The OLD SAVEPOINT LEVEL means that any SAVEPOINT statements issued within the procedure are created in the same save point level as the caller of the procedure. Thus, any save point created inside the stored procedure must not have the same name as those defined at the caller. This is the default behavior.

The NEW SAVEPOINT LEVEL, on the other hand, creates a new save point level when the stored procedure is called. Any save points set within the procedure are created at a level that is nested deeper than the level at which this procedure was invoked. Therefore, names of any new save point set within the procedure will not conflict with any existing save points.

You can also make stored procedure calls from inline SQL such as SQL functions, triggers, and stand-alone code. Such a procedure will be executed as if it were created in the NEW SAVEPOINT LEVEL mode even if the OLD SAVEPOINT LEVEL was specified.

Save points are discussed in more detail in Chapter 10, “Leveraging DB2 Application Development Features.”

LANGUAGE SQL

LANGUAGE SQL identifies this procedure as an SQL procedure, and indicates that the body of the procedure will be specified in the CREATE PROCEDURE statement body. LANGUAGE SQL is an optional clause for LUW. For iSeries and zSeries, LANGUAGE SQL must be specified. Furthermore, on iSeries, it must be specified as the first clause.

The LANGUAGE keyword is required when creating procedures in other languages such as Java or C.

EXTERNAL ACTION or NO EXTERNAL ACTION

This clause is only available on LUW. If the SQL procedure takes some action that changes the state of an object not managed by DB2, specify the EXTERNAL ACTION. Otherwise, use NO EXTERNAL ACTION so that DB2 can use certain optimizations that assume the procedure has no external impact.

PARAMETER CCSID

CCSID stands for Coded Character Set ID. This clause specifies the encoding scheme used for all string data passed into and out of the stored procedure for LUW and zSeries. Possible values are ASCII, UNICODE, and EBCDIC (for zSeries only).

On iSeries, the specification of the CCSID is at a more granular level. You specify the CCSID for each string parameter of the procedure (CHAR, VARCHAR, CLOB, GRAPHIC, VARGRAPHIC, and DBCLOB). There are numerous options for specifying CCSID on iSeries. Refer to the iSeries SQL Reference for a listing of valid CCSIDs and the allowed conversions between these CCSIDs.

On zSeries, the CCSID can be specified at either the parameter level, the subsystem level in the field DEF ENCODING SCHEME on installation panel DSNTIPF, or at the SQL procedure level. The default is the value specified at the parameter level or the subsystem level. If specified at both the parameter level and the SQL procedure, they must be the same CCSID value for all parameters.

SQL Procedure Body

For SQL procedures, the logic of the procedure is contained in the SQL procedure body of the CREATE PROCEDURE statement. The SQL procedure body can consist of a single SQL statement or several SQL statements in the form of a compound SQL statement. The next section explains the details of writing the SQL procedure body.

The SQL Procedure Body Structure

The SQL procedure body can consist of a single SQL statement or, more typically, a compound SQL statement consisting of a BEGIN/END block with multiple statements within it. The compound statement consists of various declarations followed by SQL procedure statements. All declarations must be specified first followed by SQL procedural statements. The syntax diagram in Figure 2.5 shows the required order of declarations.

Example 2.5. Compound statement syntax diagram.

                         .-NOT ATOMIC--.
>>-+---------+--BEGIN----+-------------+------------------------>
   '-label:--'           '-ATOMIC------'


>-----+-----------------------------------------------+--------->
      | .------------------------------------------.  |
      | V                                          |  |
      '-----+-| SQL-variable-declaration |-+---;---+--'
            +-| condition-declaration |----+
            '-| return-codes-declaration |-'


>--+----------------------------------+------------------------->
   | .------------------------------. |
   | V                              | |
   '---| statement-declaration |--;-+-'


>-----+--------------------------------------+------------------->
      |  .--------------------------------.  |
      |  V                                |  |
      '----DECLARE-CURSOR-statement--;----+--'


>-----+-------------------------------------+-------------------->
      |  .-------------------------------.  |
      |  V                               |  |
      '----| handler-declaration |--;----+--'


      .-------------------------------.
      V                               |
>--------SQL-procedure-statement--;---+---END--+--------+------><
                                               '-label--'

Variable declarations are discussed later in this chapter. Compound statements are discussed in Chapter 4, “Using Flow of Control Statements.” Cursor declarations are discussed in Chapter 5, “Understanding and Using Cursors and Result Sets.” Condition handlers are discussed in Chapter 6, “Condition Handling.” Statement declarations, available in LUW, are discussed in Chapter 7, “Working with Dynamic SQL.”

Comments

It is always good practice to include comments in programs. DB2 allows two styles of comments:

  • When two dashes are specified, any text following them is treated as a comment. This style is typically used to comment on a specific variable declaration or statement. It can be used on any line of the CREATE PROCEDURE statement and terminates with the newline character.

  • /* */ are C-style comments. The /* begins a comment and */ ends the comment. There may be multiple lines of comments between the delimiters. This style can be used in the body of an SQL procedure only.

Figure 2.6 are examples of comments used in an SQL procedure.

Example 2.6. Sample comments.

CREATE PROCEDURE proc_with_comments ( IN aaa INTEGER
                                    , OUT bbb INTEGER )
    LANGUAGE SQL
    SPECIFIC proc_with_comments                   -- applies to LUW and iSeries
 -- WLM ENVIRONMENT <env>                         -- applies to zSeries
BEGIN
    /*
      Variables
    */
    DECLARE v_total INTEGER DEFAULT 0;
    SELECT 1 INTO v_total FROM SYSIBM.SYSDUMMY1;
END

Variables

The DECLARE statement is used to define variables within a compound SQL statement (see Figure 2.7). Each variable declaration consists of a name for the variable, a DB2 data type, and optionally a default value.

Example 2.7. Defining variables.

CREATE PROCEDURE proc_with_variables (IN p_empno VARCHAR(6))
    LANGUAGE SQL
    SPECIFIC proc_with_vars                     -- applies to LUW and iSeries
    -- WLM ENVIRONMENT <env>                    -- applies to zSeries
BEGIN
    DECLARE v_empno VARCHAR(6);
    DECLARE v_total, v_count INTEGER DEFAULT 0;
    SELECT empno INTO v_empno FROM employee WHERE empno = p_empno ;
END

Variable declarations must be specified at the beginning of a BEGIN/END block before any SQL procedural statements are defined. The CREATE PROCEDURE statement will fail if a DECLARE is found anywhere else.

You should ensure that the variables defined in your procedure are different from column names of tables that will be referenced in the procedure. Such a declaration is allowed but only causes confusion. It is recommended that you define a naming convention for your procedures that clearly differentiates variables and columns. In this book, the convention is to precede variables with a prefix of v_ and precede procedures parameters with a prefix of p_ to differentiate them from possible column names.

When variables are declared, they are initialized as NULL unless the DEFAULT clause is used to initialize the variable to a value. In Figure 2.7 the value of v_empno is null until it is set within the procedure body. The integer variables v_total and v_count are initialized to zero in the declaration.

Setting Variables

As in any programming language, you can initialize or set variables. There are several ways to set variables in SQL procedures, and they are demonstrated in Figure 2.8.

Example 2.8. Setting variables.

CREATE PROCEDURE set_variables ()
    LANGUAGE SQL
    SPECIFIC set_variables                       -- applies to LUW and iSeries
    -- WLM ENVIRONMENT <env>                     -- applies to zSeries


BEGIN
    DECLARE v_rcount INTEGER;
    DECLARE v_max DECIMAL(9,2);
    DECLARE v_adate,v_another DATE;
    DECLARE v_total INTEGER DEFAULT 0;                -- (1)
    SET v_total = v_total + 1;                        -- (2)
    SELECT MAX(salary) INTO v_max FROM employee;      -- (3)
    VALUES CURRENT DATE INTO v_adate;                 -- (4)
    SELECT CURRENT DATE, CURRENT DATE
      INTO v_adate, v_another
      FROM SYSIBM.SYSDUMMY1;                          -- (5)
END

When declaring a variable, you can specify a default value using the DEFAULT clause as in Line (1).

Line (2) shows that a SET can be used to set a single variable.

Variables can also be set by executing a SELECT or FETCH statement in combination with INTO as shown in (3). Details on using FETCH can be found in Chapter 4, “Understanding and Using Cursors and Result Sets.”

Lines (4) and (5) show how the VALUES INTO statement can be used to evaluate a function or special register and assign the value to a variable. Special registers are discussed in more detail in the next section.

DB2 Special Registers

Recall that special registers are memory registers that allow DB2 to provide information to an application about its environment. They can be referenced in SQL statements. The most commonly used special registers are

  • CURRENT DATE. A date based on the time-of-day clock at the database server. If this register is referenced more than once in a single statement, the value returned will be the same for all references. This is a non-updateable register.

  • CURRENT ISOLATION (LUW only). Identifies the isolation level for any dynamic SQL statements issued within the current session.

  • CURRENT LOCK TIMEOUT (LUW only). Specifies the number of seconds that an application will wait to obtain a lock. This is an updateable register.

  • CURRENT PATH. Identifies the SQL path used to resolve procedure, functions, and data type references for dynamically prepared SQL statements. The value of the CURRENT PATH special register is a list of one or more schema names. This is an updateable register.

  • CURRENT PACKAGE PATH (LUW and zSeries only). Identifies the path to be used when resolving references to packages. This is an updateable register.

  • CURRENT SCHEMA. Identifies the schema name used to qualify unqualified database objects in dynamic SQL statements. The default value is the authorization ID of the current user or the value of CURRENT SQLID on zSeries. This special register can be modified using the SET CURRENT SCHEMA statement. This is an updateable register.

  • CURRENT TIME. A time based on the time-of-day clock at the database server. If this register is referenced more than once in a single statement, the value returned will be the same for all references. This is a non-updateable register.

  • CURRENT TIMESTAMP. A timestamp based on the time-of-day clock at the database server. If this register is referenced more than once in a single statement, the value returned will be the same for all references. This is a non-updateable register.

  • USER. Specifies the runtime authorization ID used to connect to the database. This is a non-updateable register.

  • SESSION_USER (LUW only). Specifies the authorization ID to be used for the current session. This is a synonym for the USER special register. This is a non-updateable register.

  • SYSTEM_USER (LUW only). Specifies the authorization ID of the user who connected to the database. This is a non-updateable register.

Special registers can be categorized as updateable and non-updateable. For example, CURRENT SCHEMA and CURRENT PATH are both updateable registers. CURRENT TIMESTAMP is an example of a non-updateable register. To obtain the value of the register, use the SELECT statement as shown:

SELECT CURRENT SCHEMA FROM SYSIBM.SYSDUMMY1;

Use the SET command to update the updateable registers such as the current schema:

SET CURRENT SCHEMA = DB2ADMIN

When invoking SQL procedures with unqualified names, the CURRENT PATH special register is used to resolve the requested SQL procedure. The path is a list of schemas which DB2 searches to locate a procedure. To obtain the CURRENT PATH special register, connect to the database and simply issue this command

SELECT CURRENT PATH FROM SYSIBM.SYSDUMMY1;

The default setting for the PATH register in LUW looks like

"SYSIBM", "SYSFUN", "SYSPROC", "DB2ADMIN"

The default PATH is made up of system schemas followed by the current user connected to the database. On LUW, SYSIBM, SYSFUN, and SYSPROC are the system schemas. With the previously shown PATH, DB2 first searches for the procedure in schema SYSIBM, then SYSFUN, then SYSPROC, and lastly DB2ADMIN. If there are overloaded procedures in both SYSPROC and DB2ADMIN, the SYSPROC one will be used. Sometimes you might want to use the DB2ADMIN procedure instead. In that case, set the CURRENT PATH to customize the search order of the schemas:

SET CURRENT PATH = DB2ADMIN,SYSIBM,SYSFUN,SYSPROC

Figure 2.9 shows the use of several special registers.

Example 2.9. Using special registers.

CREATE PROCEDURE registersample ( OUT p_start TIMESTAMP
                                , OUT p_end   TIMESTAMP
                                , OUT p_c1    TIMESTAMP
                                , OUT p_c2    TIME
                                , OUT p_user  CHAR(20))
    LANGUAGE SQL
    SPECIFIC registersample                       -- applies to LUW and iSeries
 -- WLM ENVIRONMENT <env>                         -- applies to zSeries
BEGIN
    CREATE TABLE datetab (c1 TIMESTAMP,c2 TIME,c3 DATE);


    VALUES CURRENT TIMESTAMP INTO p_start;               -- (1)
    INSERT INTO datetab VALUES( CURRENT TIMESTAMP
                               , CURRENT TIME
                               , CURRENT DATE + 3 DAYS); -- (2)
    SELECT c1,c2 INTO p_c1,p_c2 FROM datetab;
    VALUES CURRENT TIMESTAMP INTO p_end;
    SET p_user = USER;                                   -- (3)
    DROP TABLE datetab;
END

The procedure registersample creates a table, datetab, to demonstrate how special registers are used with SQL statements. This table is dropped at the end so that the procedure can be run repeatedly.

On Line (1), the values statement is used to set the variable p_start to the current timestamp.

Line (2) shows several special registers being used within a single SQL statement to retrieve the date or time. Here, the time portion of the CURRENT TIMESTAMP special register will be the same as the value of the CURRENT TIME special register, and date portion of the CURRENT TIMESTAMP special register will be the same as the value of CURRENT DATE. This statement also demonstrates the use of built-in functions. Column c3 will receive a date that is three days from the current date. You can find more details on using built-in functions such as DATE, TIME, and TIMESTAMP in the DB2 SQL Reference.

The p_user variable is set to the authorization ID of the currently connected user on Line (3).

The following list includes other special registers that are available. More information about them can be found in the DB2 SQL Reference for the corresponding platform.

  • CURRENT APPLICATION ENCODING SCHEME (zSeries only). Specifies which encoding scheme is to be used for dynamic statements. It allows an application to indicate the encoding scheme that is used to process data. This is an updatable register.

  • CURRENT DBPARTITIONNUM (LUW only). Specifies an INTEGER value that identifies the coordinator node number for the statement. This is a non-updateable register.

  • CURRENT DEFAULT TRANSFORM GROUP (LUW only). Identifies the name of a transform group used by dynamic SQL statements for exchanging user-defined structured type values with host programs. This is an updateable register.

  • CURRENT DEGREE (LUW and zSeries only). Specifies the degree of intra-partition parallelism for the execution of dynamic SQL statements. This is an updateable register.

  • CURRENT EXPLAIN MODE (LUW only). Holds a value that controls the behavior of the Explain facility. This is an updateable register.

  • CURRENT EXPLAIN SNAPSHOT (LUW only). Holds a value that controls behavior of the Explain Snapshot facility. This is an updateable register.

  • CURRENT LOCALE LC_CTYPE (zSeries only). Specifies the LC_CTYPE locale that will be used to execute SQL statements which use a built-in function that references a locale. This is an updatable register.

  • CURRENT MAINTAINED TABLE TYPES FOR OPTIMIZATION (LUW and zSeries only). Specifies the types of tables that can be considered for optimization when dynamic SQL queries are processed. This is an updateable register.

  • CURRENT MEMBER (zSeries only). Specifies the member name of a current DB2 data sharing member on which a statement is executing. This is a non-updatable register.

  • CURRENT OPTIMIZATION HINT (zSeries only). Specifies the user-defined optimization hint that DB2 should use to generate the access path for dynamic statements. This is an updateable register.

  • CURRENT PRECISION (zSeries only). Specifies the rules to be used when both operands in a decimal operation have precisions of 15 or less. This is an updatable register.

  • CURRENT QUERY OPTIMIZATION (LUW only). Specifies the query optimization level used when binding dynamic SQL statements. This is an updateable register.

  • CURRENT REFRESH AGE (LUW and zSeries only). Specifies the maximum duration that a cached data object, such as a materialized query table, can be used for dynamic queries before it must be refreshed. This is an updateable register.

  • CURRENT RULES (zSeries only). Specifies whether certain SQL statements are executed in accordance with DB2 rules or the rules of the SQL standard. This is an updatable register.

  • CURRENT SERVER. Specifies the name of the database to which the application is connected. This is a non-updateable register.

  • CURRENT TIMEZONE. Specifies the difference between UTC (Coordinated Universal Time) and local time at the application server. This is a non-updateable register.

  • CLIENT ACCTNG (LUW and zSeries only). Specifies the accounting string for the client connection. On zSeries, use CURRENT CLIENT_ACCTNG. This is an updateable register.

  • CLIENT APPLNAME (LUW and zSeries only). Specifies the client application name. On zSeries, use CURRENT CLIENT_APPLNAME. This is an updateable register.

  • CLIENT USERID (LUW and zSeries only). Specifies the client user ID. On zSeries, use CURRENT CLIENT_USERID. This is an updateable register.

  • CLIENT WRKSTNNAME (LUW and zSeries only). Specifies the client workstation name. On zSeries, use CURRENT CLIENT_WRKSTNNAME. This is an updateable register.

Bringing It All Together Example

A detailed example is presented in this section to demonstrate all the basic features discussed thus far. The procedure in Figure 2.10 inserts a row into the employee table of the SAMPLE database. If you have not created the SAMPLE database, see Appendix A, “Getting Started with DB2.” We recommend that you create this database because most examples in this book make use of it to demonstrate concepts.

Example 2.10. add_new_employee procedure

CREATE PROCEDURE add_new_employee ( IN  p_empno     VARCHAR(6)    -- (1)
                                  , IN  p_firstnme CHAR(12)
                                  , IN  p_midinit   CHAR(1)
                                  , IN  p_lastname  VARCHAR(15)
                                  , IN  p_deptname  VARCHAR(30)
                                  , IN  p_edlevel   SMALLINT
                                  , OUT p_status    VARCHAR(100)
                                  , OUT p_ts        TIMESTAMP)
    LANGUAGE SQL
    SPECIFIC add_new_employee             -- applies to LUW and iSeries
    -- WLM ENVIRONMENT <env>              -- applies to zSeries


BEGIN
    DECLARE v_deptno CHAR(3) DEFAULT '   ';                       -- (2)
    DECLARE v_create_ts TIMESTAMP;                                -- (3)
    SET v_create_ts = CURRENT TIMESTAMP;
    /* Get the corresponding department number */
    SELECT deptno
      INTO v_deptno                                               -- (4)
      FROM department
     WHERE deptname = p_deptname;


     /* Insert new employee into table */                         -- (5)
     INSERT INTO employee ( empno
                          , firstnme
                          , midinit
                          , lastname
                          , workdept
                          , hiredate
                          , edlevel)
     VALUES ( p_empno
            , p_firstnme
            , p_midinit
            , p_lastname
            , v_deptno
            , DATE(v_create_ts)
            , p_edlevel );

     SET p_status = 'Employee added';                             -- (6)
     SET p_ts = v_create_ts;                                      -- (7)
END

The parameter list shown in Line (1) defines input and output variables to the procedures. The input parameters represent column values that will be inserted into the Employee table. Note that the p_ prefix is used for each variable to differentiate variables from column names. The output parameters are used to return a status and the TIMESTAMP of the execution of the procedure.

Line (2) declares the v_deptno variable to hold the department number retrieved from the Department table. v_deptno is initialized to ’ ’.

Line (3) declares the v_create_ts variable to hold the TIMESTAMP of execution of the procedure. To ensure that the same value of hiredate is used to insert into the Employee table, the CURRENT TIMESTAMP register is retrieved only once in the procedure.

To look up the department number in the Department table, a SELECT statement shown in Line (4) is used to retrieve deptno and saved in v_deptno.

Line (5) inserts into the Employee table using parameter values v_deptno and v_create_ts. The value of v_create_ts, which is of type TIMESTAMP, must be cast to DATE using the DATE casting function.

On Lines (6) and (7), the output parameters p_status and p_ts are set.

To execute the add_new_employee procedure on LUW, enter the following in CLP:

CALL add_new_employee('123456','ROBERT','K','ALEXANDER','PLANNING',1,?,?)

The output of this call is

P_STATUS: Employee added
P_TS: 2002-09-29 17:19:10.927001

"ADD_NEW_EMPLOYEE" RETURN_STATUS: "0"

The results of many examples in the book are shown using the CLP on LUW. The output will vary based on the operating system. For example, if you are using the Run an SQL Script window of the iSeries Navigator, the output from the call above would be

Output Parameter #7 = Employee added
Output Parameter #8 = 2002-09-29 17:19:10.927001

Statement ran successfully   (591 ms)

DB2 UDB for iSeries Considerations

The CREATE PROCEDURE statement syntax for DB2 UDB for iSeries is very similar to the CREATE PROCEDURE statement syntax for DB2 UDB for distributed platforms shown in Figure 2.1. In iSeries, the following is true:

  • The LANGUAGE SQL clause is mandatory and must be listed right after the parameter declaration in the procedure.

  • The PARAMETER CCSID clause is not supported, but specification of the encoding scheme can be specified with the data type of the parameters.

  • The EXTERNAL ACTION clause is not part of the syntax.

  • An option to specify whether the procedure runs FENCED or NOT FENCED is supported for compatibility with other products in the DB2 family.

  • A COMMIT ON RETURN clause can be specified to commit a transaction when returning from a SQL procedure.

  • An optional SET OPTION clause is supported to specify precompile options.

For completeness, Figure 2.11 shows the syntax diagram for the iSeries CREATE PROCEDURE statement, followed by a more detailed explanation of some of the clauses.

Example 2.11. CREATE PROCEDURE statement syntax for DB2 UDB for iSeries.

>>-CREATE PROCEDURE---procedure-name --------------------------->


>--+----------------------------------------------------------+->
   '--(--+----------------------------------------------+--)--'->
         |  .-,---------------------------------------. |
         |  V .-IN----.                               | |
         '----+-------+---parameter-name--data-type---+-'
              +-OUT---+
              '-INOUT-'


>--LANGUAGE SQL-----------------------------------------------+->


   .-NOT DETERMINISTIC--.     .-MODIFIES SQL DATA--.
>--+--------------------+-----+--------------------+------------>
   '-DETERMINISTIC------'     +-CONTAINS SQL-------+
                              '-READS SQL DATA-----'


   .-CALLED ON NULL INPUT-.
>--+----------------------+-----+--------------------------+---->
                                '-SPECIFIC--specific-name--'

   .-DYNAMIC RESULT SETS 0---------.     .-FENCED-----.
>--+-------------------------------+-----+------------+--------->
   '-DYNAMIC RESULT SETS--integer--'     '-NOT FENCED-'

   .-COMMIT ON RETURN NO--.     .-OLD SAVEPOINT LEVEL-.
>--+----------------------+-----+---------------------+--------->
   '-COMMIT ON RETURN YES-'     '-NEW SAVEPOINT LEVEL-'


   .-INHERIT SPECIAL RESGISTERS-.
>--+----------------------------+------------------------------->


>--+---------------------+---SQL-routine-body------------------><
   '-SET OPTION-statement-'

FENCED and NOT FENCED

This option is provided only for compatibility with other products in the DB2 family and is not used by SQL procedures in DB2 UDB for iSeries.

COMMIT ON RETURN

This clause can be specified to tell the database manager to commit the transaction when returning from the SQL procedure call. The default value is NO. If a value of YES is specified, the transaction is committed only upon successful completion of the procedure. If an error is encountered, a COMMIT is not issued.

SET OPTION Statement

The SET OPTION statement is used to specify processing options that will be used to create the procedure. For example, a procedure can be created for debug by specifying the following:

SET OPTION DBGVIEW = *SOURCE

DBGVIEW identifies that debug information is to be provided by the compiler. The *SOURCE specifies that the compiled object is to be debugged using the program source code.

Chapter 12, “Performance Tuning,” discusses the SET OPTION statement in more detail. For a complete list of options, refer to the SET OPTION statement information found in the Statements chapter of the DB2 UDB for iSeries SQL Reference.

DB2 UDB for zSeries Considerations

In DB2 UDB for zSeries, the CREATE PROCEDURE statement defines a procedure in the DB2 subsystem. Figure 2.12 shows the syntax diagram of such a statement. It is very similar to the syntax shown in Figure 2.1 for DB2 for LUW. In zSeries, the following is true:

  • The LANGUAGE SQL clause is mandatory.

  • The SPECIFIC, SAVEPOINT LEVEL, and EXTERNAL ACTION clauses are not part of the syntax.

  • PARAMETER CCSID has an extra possible value of EBCDIC. In addition, the CCSID clause can be included with each stored procedure parameter.

  • The FENCED clause is the default value and an optional clause. There is no NOT FENCED option.

  • A COMMIT ON RETURN clause can be specified to commit a transaction when returning from an SQL procedure.

Example 2.12. CREATE PROCEDURE statement syntax in DB2 UDB for zSeries.

>>-CREATE PROCEDURE--------------------------------------------->

>----procedure-name--(--+----------------------------------------------+---)->
                        | .-,----------------------------------------.  |
                        | V .-IN-----.                               | |
                        '----+-------+---parameter-name--data-type---+-'
                             +-OUT---+
                             '-INOUT-'

   .-DYNAMIC RESULT SETS 0--------.     .-MODIFIES SQL DATA-.
>--+------------------------------+--*--+-------------------+--->
   '-DYNAMIC RESULT SETS--integer-'     +-CONTAINS SQL------+
                                        '-READS SQL DATA----'


      .-NOT DETERMINISTIC-.     .-CALLED ON NULL INPUT-.
>--*--+-------------------+--*--+----------------------+--*----->
      '-DETERMINISTIC-----'


   .-INHERIT SPECIAL REGISTERS-.
>--+---------------------------+--*-------LANGUAGE SQL---------->
   '-DEFAULT SPECIAL REGISTERS-'


                                      .-FENCED-.   .-NO DBINFO-.
>--+------------------------------+---+--------+---+-----------+->
   '-PARAMETER CCSID--+-ASCII---+-'
                      '-EBCDIC -'
                      '-UNICODE-'


   .-NO COLLID ------------.
>--+-----------------------+---+-------------------------------+->
   '-COLLID Collection-Id -'   '-WLM ENVIRONMENT--+--name----+-'
                                                  '-(name,*)-'


   .-ASUTIME NO LIMIT ------.    .-STAY RESIDENT NO--.
>--+------------------------+----+-------------------+----------->
   '-ASUTIME LIMIT integer--'    +-STAY RESIDENT YES-'



   .-PROGRAM TYPE MAIN--.    .-SECURITY DB2-----.
>--+--------------------+----+------------------+---------------->
   '-PROGRAM TYPE SUB---'    +-SECURITY USER ---+
                             '-SECURITY DEFINER-'




                                        .-COMMIT ON RETURN NO---.
>--+-------------------------------+----+-----------------------+->
   '-RUN OPTIONS run time options--'    '-COMMIT ON RETURN YES--'



   .-STOP AFTER SYSTEM DEFAULT FAILURES --.
>--+--------------------------------------+---------------------->
   +-STOP AFTER integer FAILURES ---------+
   '-CONTINUE AFTER FAILURE---------------'


>-----| SQL-procedure-body |------------------------------------><

SQL-procedure-body:


 |---SQL-procedure-statement-------------------------------------|

FENCED

This option specifies that the SQL procedure runs in an external address space to prevent user programs from corrupting the DB2 engine storage. This clause is optional and is the default value in DB2 UDB for zSeries. There is no NOT FENCED option. Note that SQL procedures created in DB2 UDB for LUW are all UNFENCED; this is the default and the only behavior.

NO DBINFO

NO DBINFO indicates that specific internal information known to DB2 will not be passed to the SQL procedure. NO DBINFO is the default for SQL procedures.

NO COLLID or Collid collection-id

NO COLLID indicates that the package collection for the SQL procedure is the same as the package collection of the calling program. COLLID collection-id provides the collection ID to be used for the SQL procedure.

WLM ENVIRONMENT

This option identifies the Workload Manager (WLM) environment where the SQL procedure is to run if defined as a WLM-established SQL procedure. If WLM ENVIRONMENT is not specified, the default WLM environment specified at installation time is used.

ASUTIME

This option indicates whether the SQL procedure will use unlimited processor time for a single invocation of an SQL procedure (NOLIMIT) or a specific amount of processor time (LIMIT integer).

STAY RESIDENT

This option indicates the SQL procedure will remain in memory when it ends (YES) or not (NO).

PROGRAM TYPE

This option specifies whether the SQL procedure will run as a subroutine (SUB) or as a main program (MAIN).

SECURITY

This option indicates how the SQL procedure interacts with an external security product to control access to non-SQL resources. Possible values include the following:

  • DB2. The SQL procedure does not require a special external security environment. If it accesses resources that an external security product protects, the access is performed using the authorization ID associated with the SQL procedure address space. DB2 is the default.

  • USER. An external security environment should be established for the SQL procedure. If the SQL procedure accesses resources that the external security product protects, the access is performed using the authorization ID of the user who invoked the SQL procedure.

  • DEFINER. An external security environment should be established for the SQL procedure. If the SQL procedure accesses resources that the external security product protects, the access is performed using the authorization ID of the owner of the SQL procedure.

RUN OPTIONS

This option indicates the Language Environment runtime options that are to be used for the SQL procedure.

COMMIT ON RETURN

This option indicates whether a COMMIT is automatically issued upon return from the SQL procedure, regardless of whether a COMMIT or ROLLBACK is explicitly coded in the SQL procedure. NO is the default.

STOP AFTER SYSTEM DEFAULT FAILURES or CONTINUE AFTER FAILURE

This option indicates whether the SQL procedure is to be put in a stopped state after some number of failures. Possible values include the following:

  • STOP AFTER SYSTEM DEFAULT FAILURESThe value of field MAX ABEND COUNT on installation panel DSNTIPX is used to determine the number of failures allowed before placing the SQL procedure in stopped state. This is the default.

  • STOP AFTER nn FAILURESIndicates that after nn failures, the SQL procedure should be placed in a stopped state. The value nn can be an integer from 1 to 32767.

  • CONTINUE AFTER FAILURESpecifies that this SQL procedure should not be placed in a stopped state after any failure.

Summary

SQL procedures are defined using the CREATE PROCEDURE statement. The statement defines the name, the parameters, and several other properties of the procedure.

The SQL procedure logic is defined in the procedure body of the CREATE PROCEDURE statement. The body is typically a compound statement consisting of declarations followed by procedural statements. The DECLARE statement is used to declare variables, their data type, and optionally, a default value. Statements such as SET, SELECT...INTO, and VALUES can also be used to assign values to variables.

This chapter demonstrated creation of simple procedures with some basic procedural statements. Other SQL PL statements will be discussed in detail in the rest of this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.134.232