compound-statement

Start of changeA compound statement groups other statements together in an SQL routine or advanced trigger.End of change A compound statement allows the declaration of SQL variables, cursors, and condition handlers.

Syntax

Read syntax diagramSkip visual syntax diagramlabel:BEGINNOT ATOMICATOMICSQL-variable-declarationSQL-condition-declarationreturn-codes-declaration;statement-declaration;DECLARE-CURSOR-statement;handler-declaration;SQL-procedure-statement;END label

SQL-variable-declaration:

Read syntax diagramSkip visual syntax diagramDECLARE,SQL-variable-namedata-typeDEFAULT NULLCONSTANT NULLDEFAULTCONSTANTconstantRESULT_SET_LOCATOR VARYING

SQL-condition-declaration:

Read syntax diagramSkip visual syntax diagramDECLARESQL-condition-nameCONDITIONFORSQLSTATEVALUEstring-constant

return-codes-declaration:

Read syntax diagramSkip visual syntax diagramDECLARE SQLSTATECHAR(5)CHARACTER(5)DEFAULT '00000'DEFAULTstring-constantSQLCODEINTEGERINTDEFAULT 0DEFAULTinteger-constant

statement-declaration:

Read syntax diagramSkip visual syntax diagramDECLARE,statement-nameSTATEMENT1
Notes:
  • 1 The statement is not allowed in an SQL-routine-body for an SQL function.

handler-declaration:

Read syntax diagramSkip visual syntax diagramDECLARECONTINUEEXITHANDLERFOR specific-condition-valuegeneral-condition-valueSQL-procedure-statement

specific-condition-value:

Read syntax diagramSkip visual syntax diagram,SQLSTATEVALUEstring-constantcondition-name

general-condition-value:

Read syntax diagramSkip visual syntax diagram,SQLEXCEPTIONSQLWARNINGNOT FOUND

Description

label
Specifies the label for the compound-statement. If the beginning label is specified, it can be used to qualify SQL variables declared in the compound statement and can also be specified as the target on a LEAVE statement. If the ending label is specified, it must be the same as beginning label. Start of changeThe label name cannot be the same as the routine name, trigger name, or another label within the same scope.End of change
Start of changeATOMIC or NOT ATOMICEnd of change
Start of changeFL 500Specifies whether an unhandled exception condition within a compound-statement causes that compound statement to be rolled back. The default for the outermost compound statement in an advanced trigger is ATOMIC; otherwise the default is NOT ATOMIC.
ATOMIC
ATOMIC indicates that an unhandled exception condition within the compound-statement causes the compound-statement to be rolled back. ATOMIC must not be specified in a compound statement in an SQL scalar function, in an SQL procedure, or in a compound statement that is nested within another compound statement that is defined as ATOMIC.
NOT ATOMIC
NOT ATOMIC indicates that an unhandled exception condition within the compound-statement does not cause the compound-statement to be rolled back. NOT ATOMIC must not be specified in the outermost compound statement of an advanced trigger.
End of change
SQL-variable-declaration
Declares a variable that is local to the compound statement.
SQL-variable-name
Defines the name of a variable. Db2 converts all SBCS SQL variable names that are not delimited to uppercase. SQL-variable-name must be unique within the compound statement in which is it declared, excluding any declarations in compound statements that are nested within that compound statement. SQL-variable-name must not be the same as a parameter name. See References to SQL parameters and variables in SQL PL for information about how SQL variable names are resolved when there are columns with the same name as an SQL variable involved in a statement, or when multiple SQL variables exist with the same name in the routine body.

SQL-variable-name can only be referenced within the compound statement in which it is declared, including any compound statement that is nested within that compound statement. If the compound statement where the variable is declared has a label, references to the variable name can be qualified with that label. For example, an SQL variable V that is declared in a compound statement that is labeled C can be referenced as C.V.

data-type
Specifies the data type and length of the variable. SQL variables follow the same rules for default lengths and maximum lengths as SQL routine parameters. See CREATE FUNCTION statement (compiled SQL scalar function) for descriptions of SQL data types and lengths.
Start of changeDEFAULT or CONSTANTEnd of change
Start of changeFL 500Specifies a value for the SQL variable when the compound statement in which it is declared is entered. If neither DEFAULT nor CONSTANT is specified, the default for the SQL variable is the null value. Only DEFAULT NULL can be explicitly specified if array-type-name is specified. Only DEFAULT NULL or CONSTANT NULL can be specified for an SQL variable with the XML data type.
DEFAULT
Defines the default for the SQL variable. The specified constant must represent a value that could be assigned to the variable in accordance with the rules of assignment as described in Assignment and comparison.
CONSTANT
Specifies that the SQL variable has a fixed value that cannot be changed. An SQL variable that is defined using CONSTANT cannot be used as the target of any assignment operation. The specified constant must represent a value that could be assigned to the variable in accordance with the rules of assignment as described in Assignment and comparison.

Variables that are named SQLCODE and SQLSTATE cannot be defined using CONSTANT.

NULL
Specifies NULL as the default for the SQL variable.
constant
Specifies a constant as the default for the SQL variable.
End of change
RESULT_SET_LOCATOR VARYING
Specifies the data type for a result set locator variable.
SQL-condition-declaration
Declares a condition name and corresponding SQLSTATE value.
SQL-condition-name
Specifies the name of the condition. The condition name must be unique within the compound statement in which it is declared, excluding any declarations that are in compound statements that are nested within that compound statement. A condition name can only be referenced within the compound statement in which it is declared, including any compound statements that are nested within that compound statement.
FOR SQLSTATE string-constant
Specifies the SQLSTATE that is associated with the condition. The string must be specified as five characters enclosed in single quotes, and the SQLSTATE class (the first two characters) must not be '00'.
return-codes-declaration
Declares special variables named SQLSTATE and SQLCODE. These variables are automatically set to the SQLSTATE and SQLCODE values for the first condition in the diagnostics area after executing an SQL statement other than GET DIAGNOSTICS or an empty compound statement.

The SQLSTATE and SQLCODE SQL variables are only intended to be used as a means of obtaining the SQL return codes that resulted from processing the previous SQL statement other than GET DIAGNOSTICS. If there is any intention to use the SQLSTATE and SQLCODE values, save the values immediately to other SQL variables to avoid having the values replaced by the SQL return codes returned after executing the next SQL statement. If a handler is defined that handles an SQLSTATE, you can use an assignment statement to save that SQLSTATE (or the associated SQLCODE) value in another SQL variable, if the assignment is the first statement in the handler.

Assignment to these variables is not prohibited; however, it is not recommended. Assignment to these variables is ignored by condition handlers, and processing an assignment to these special variables causes the specified values for the assignment to be overlayed with the SQL return codes returned from executing the statement that does the assignment. The SQLSTATE and SQLCODE SQL variables cannot be set to NULL.

statement-declaration
Declares a list of one or more names that are local to the compound statement. A statement name cannot be the same as another statement name within the same compound statement.
DECLARE-CURSOR-statement
Declares a cursor in the procedure body. Each cursor must have a unique name within the routine. The cursor can only be referenced from within the compound statement in which it is declared, including any compound statements that are nested within that compound statement. Use an OPEN statement to open the cursor, a FETCH statement to read a row using the cursor, and a CLOSE statement to close the cursor. If the cursor is intended for use as a result set cursor:
  • Specify WITH RETURN when the cursor is declared
  • Create the procedure using the DYNAMIC RESULT SETS clause with a non-zero value
  • Do not specify a CLOSE statement for the cursor in the compound statement
For additional information about declaring a cursor, see DECLARE CURSOR statement.
handler-declaration
Specifies a condition handler, an SQL-procedure-statement to execute when an exception or completion condition occurs in the compound-statement. The SQL-procedure-statement executes when a condition handler receives control.

A condition handler declaration cannot reference the same condition value or SQLSTATE value more than one time. It cannot reference an SQLSTATE value and a condition name that represent the same SQLSTATE value.

When two or more condition handlers are declared in a compound statement, no two condition handler declarations can specify the same:

  • general condition category
  • specific condition, either as an SQLSTATE value or as a condition name that represents the same value

A condition handler is active for the set of SQL-procedure-statements that follow the condition handler declarations within the compound statement in which the condition handler is declared, including any nested compound statements.

CONTINUE
Specifies that after the condition handler is activated and completes successfully, control is returned to the SQL statement that follows the statement that raised the condition. However, if the condition is an error condition and it was encountered while evaluating a search condition, as in a CASE, FOR, IF, REPEAT or WHILE statement, control returns to the statement that follows the corresponding END CASE, END FOR, END IF, END REPEAT, or END WHILE.
EXIT
Specifies that after the condition handler is activated and completes successfully, control is returned to the end of the compound statement that declared the condition handler.

The conditions that can cause the handler to gain control are:

SQLSTATE string-constant
Specifies that the handler is invoked when the specific SQLSTATE occurs. The first two characters of the SQLSTATE value must not be '00'.
SQL-condition-name
Specifies that the handler is invoked when the specific SQLSTATE that is associated with the condition name occurs. The SQL-condition-name must be declared within the compound statement that contains the handler declarations, or within a compound statement in which that compound statement is nested.
SQLEXCEPTION
Specifies that the handler is invoked when an SQLEXCEPTION occurs. An SQLEXCEPTION is an SQLSTATE in which the class code is a value other than '00', '01', or '02'. For more information on SQLSTATE values, see SQLSTATE values and common error codes.
SQLWARNING
Specifies that the handler is invoked when an SQLWARNING occurs. An SQLWARNING is an SQLSTATE value with a class code of '01'.
NOT FOUND
Specifies that the handler is invoked when a NOT FOUND condition occurs. NOT FOUND corresponds to an SQLSTATE value with a class code of '02'.

Notes

Unlike host variables, SQL variables are not preceded by colons when they are used in SQL statements.

Nesting compound statements: Compound statements can be nested. Nested compound statements can be used to scope variable definitions, condition names, condition handlers, and cursors to a subset of the statements in a routine. This can simplify the processing that is done for each SQL routine statement. Nested compound statements enable the use of a compound statement within the declaration of a condition handler.

The scope of a cursor: The scope of a cursor name is the compound statement in which it is declared, including any compound statements that are nested within that compound statement. A cursor name can only be referenced within the compound statement in which it is declared, including any compound statements that are nested within that compound statement.

Considerations for statement-name: The scope of a statement-name that is declared in a compound statement is the compound statement and any nested compound statements (unless the same statement-name is declared in a nested compound statement). If a statement-name is used in a DECLARE CURSOR statement or a PREPARE statement and has not been declared in the compound statement where it is used or any outer compound statements in which it is nested, the statement-name is assumed to be declared globally for the routine.

Condition handlers: Start of changeCondition handlers in SQL routines and advanced triggers are similar to WHENEVER statements that are used in external SQL application programs. A condition handler can be defined to automatically get control when an exception, warning, or not found condition occurs. The body of a condition handler contains code that is executed when the condition handler is activated. A condition handler can be activated as the result of an exception, a warning, or a not found condition that is returned by Db2 for the processing of an SQL statement. Or the condition that activates the handler can be the result of a SIGNAL or RESIGNAL statement that is issued within the SQL routine or trigger body.End of change

A condition handler is declared within a compound statement, and it is active for the set of SQL-procedure-statements that follow all of the condition handler declarations within the compound statement in which the condition handler is declared. For example, the scope of a condition handler declaration H is the list of SQL-procedure-statements that follow the condition handler declarations that are contained within the compound statement in which H appears. This means that the scope of H does not include the statements that are contained in the body of the condition handler H, implying that a condition handler cannot handle conditions that arise inside its own body. Similarly, for any two condition handlers H1 and H2 that are declared in the same compound statement, H1 will not handle conditions that arise in the body of H2, and H2 will not handle conditions that arise in the body of H1.

The declaration of a condition handler specifies the condition that activates it, the type of condition handler (CONTINUE or EXIT), and the handler action. The type of condition handler determines to where control is returned after the handler action successfully completes.

Condition handler activation: When a condition other than a successful completion occurs in the processing of SQL-procedure-statement, if a condition handler that could handle the condition is within scope, one such condition handler will be activated to process the condition.

In a routine with nested compound statements, condition handlers that could handle a specific condition might exist at several levels of the nested compound statements. The condition handler that is activated is a condition handler that is declared innermost to the scope in which the condition was encountered. If more than one condition handler at the nesting level could handle the condition, the condition handler that is activated is the most appropriate handler that is declared in that compound statement.

The most appropriate handler is the condition handler that most closely matches the SQLSTATE or the exception or completion condition. For a given compound statement, when both a specific handler for a condition and a general handler are declared that address the same condition, the specific handler takes precedence over the general handler.

For example, if the innermost compound statement declares a specific handler for SQLSTATE '22001', as well as a general handler for SQLEXCEPTION, the specific handler for SQLSTATE '22001' is the most appropriate handler when SQLSTATE '22001' is encountered. In this case, the specific handler is activated.

When a condition handler is activated, the condition handler action is executed. If the handler action completes successfully or with an unhandled warning, the diagnostics area is cleared, and the type of the condition handler (CONTINUE or EXIT handler) determines to where control is returned. Additionally, the SQLSTATE and SQLCODE SQL variables are cleared when a handler completes successfully or with an unhandled warning.

If the handler action does not complete successfully and an appropriate handler exists for the condition that is encountered in the handler action, that condition handler is activated. Otherwise, the condition that is encountered within the condition handler is unhandled.

Unhandled conditions: If a condition is encountered and an appropriate handler does not exist for that condition, the condition is unhandled.

  • Start of changeIf the unhandled condition is an exception, the SQL routine or advanced trigger that contains the failing statement is terminated with an unhandled exception condition.End of change
  • If the unhandled condition is a warning or is a not found condition, processing continues with the next statement. Note that the processing of the next SQL statement will cause information about the unhandled condition in the diagnostics area to be overwritten, and evidence of the unhandled condition will no longer exist.

    Start of changeIf an SQL routine or advanced trigger completes with an unhandled warning or not found condition, the condition is returned to the invoking statement. If a basic trigger completes with an unhandled warning or not found condition, the condition is not returned to the invoking statement.End of change

Considerations for using SIGNAL and RESIGNAL statements with nested compound statements: If an SQL-procedure-statement that is specified in the condition handler is either a SIGNAL or RESIGNAL statement with an exception SQLSTATE, the compound statement terminates with the specified exception. This happens even when this condition handler or another condition handler in the same compound statement specifies CONTINUE, since these condition handlers are not in the scope of this exception. If a compound statement is nested in another compound statement, condition handlers in the higher level compound statement can handle the exception because those condition handlers are within the scope of the exception.

Start of changeSQLSTATE and SQLCODE variables in SQL routines and advanced triggers: To help debug your SQL routines and advanced triggers, you might find it useful to check the SQLSTATE and SQLCODE value after executing a statement. An SQLCODE or SQLSTATE variable can be declared and subsequently referenced in an SQL routine or advanced trigger. You could insert the value of the SQLCODE and SQLSTATE into a table at various points in the SQL routine or advanced trigger, or return the SQLCODE and SQLSTATE values in a diagnostics string as an OUT parameter for an SQL procedure. To use the SQLCODE and SQLSTATE values, you must declare the following SQL variables in the SQL routine or advanced trigger body: End of change

Start of changeWhen you reference the SQLCODE or SQLSTATE variables in an SQL routine or advanced trigger, Db2 sets the value of SQLCODE to 0 and SQLSTATE to '00000' for the subsequent statement. You can also use CONTINUE condition handlers to assign the value of the SQLSTATE and SQLCODE variables to variables in your SQL routine or advanced trigger body. You can then use these SQL variables to control your routine or trigger logic, or pass the value back as an output parameter. In the following example, the SQL routine returns control to the statement following each SQL statement with the SQLCODE set in a SQL variable called RETCODE: End of change

DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE retcode INTEGER DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET retcode = SQLCODE;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET retcode = SQLCODE;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET retcode = SQLCODE;

The compound statement itself does not affect the SQLSTATE and SQLCODE SQL variables. However, SQL statements contained within the compound statement can affect the SQLSTATE and SQLCODE SQL variables. At the end of the compound statement, the SQLSTATE and SQLCODE SQL variables reflect the result of the last SQL statement executed within the compound statement that caused a change to the SQLSTATE and SQLCODE SQL variables. If the SQLSTATE and SQLCODE SQL variables were not changed within the compound statement, they contain the same values as when the compound statement was entered.

Null values in SQL parameters and SQL variables: If the value of an SQL parameter or SQL variable is null and it is used in an SQL statement that does not allow an indicator variable, an error is returned.

Effect on open cursors: At the end of the compound statement, all open cursors that are declared in that compound statement, except cursors that are used to return result sets, are closed.

Atomic processing of a compound statement: Atomic processing is not supported for a compound statement. If atomic behavior is needed for a block of code in a compound statement, set a savepoint before the nested compound statement is entered. This will allow changes to be undone with a ROLLBACK TO SAVEPOINT statement.

Examples

Example 1: Create a procedure body with a compound statement that performs the following actions:

  1. Declares SQL variables.
  2. Declares a cursor to return the salary of employees in a department determined by an IN parameter.
  3. Declares an EXIT handler for the condition NOT FOUND (end of file). The SQL procedure statement of the handler assigns the value 6666 to the OUT parameter medianSalary.
  4. Selects the number of employees in the given department into the SQL variable v_numRecords.
  5. Fetches rows from the cursor in a WHILE loop until the salary records for 50% + 1 of the employees in the department have been retrieved.
  6. Returns the median salary.
CREATE PROCEDURE DEPT_MEDIAN 
   (IN deptNumber SMALLINT, 
    OUT medianSalary DOUBLE) 
   LANGUAGE SQL 
   BEGIN 
     DECLARE v_numRecords INTEGER DEFAULT 1; 
     DECLARE v_counter INTEGER DEFAULT 0; 
     DECLARE c1 CURSOR FOR 
       SELECT salary FROM staff 
         WHERE DEPT = deptNumber 
         ORDER BY salary; 
     DECLARE EXIT HANDLER FOR NOT FOUND 
       SET medianSalary = 6666; 
   
     /* initialize OUT parameter */ 
     SET medianSalary = 0; 
     SELECT COUNT(*) INTO v_numRecords FROM staff 
       WHERE DEPT = deptNumber; 
     OPEN c1; 
     WHILE v_counter < (v_numRecords / 2 + 1) DO 
       FETCH c1 INTO medianSalary;
       SET v_counter = v_counter + 1; 
     END WHILE; 
     CLOSE c1; 
   END
Start of changeExample 2: Define an exit handler for any error, warning, or case of end of data. When this procedure is invoked successfully, the value 45000 is returned for the output parameter:
CREATE PROCEDURE JMBLIB.PROCL(OUT MEDIANSALARY INT)
  LANGUAGE SQL
  BEGIN
   DECLARE CHAR1 CHAR;
   DECLARE C1 CURSOR FOR SELECT * 
     FROM SYSIBM.SYSDUMMY1;
   DECLARE EXIT HANDLER FOR NOT FOUND, 
        SQLEXCEPTION, 
        SQLWARNING
    RETURN;
   OPEN C1;
   FETCH C1 INTO CHAR1;
   SET MEDIANSALARY = 45000;
   FETCH C1 INTO CHAR1;
   SET MEDIANSALARY = 50000;
  END
End of change