INFORMIX
Informix Guide to SQL: Syntax
Chapter 2: SPL Statements
Home Contents Index Master Index New Book

SPL Statements

In This Chapter

You can use Stored Procedure Language (SPL) statements to write routines, and you can store these SPL routines in the database. These SPL routines are effective tools for controlling SQL activity.

This chapter contains descriptions of the SPL statements. The description of each statement includes the following information:

If a statement is composed of multiple clauses, the statement description provides the same set of information for each clause.

For task-oriented information about using SPL routines, see Chapter 14 of the Informix Guide to SQL: Tutorial.

CALL

Use the CALL statement to execute a routine from within an SPL routine.

Syntax

Element Purpose Restrictions Syntax

data variable

The name of a variable that receives the value or values a function returns

The data type of data variable must be appropriate for the value the function returns.

Identifier, p. 1-966

routine variable

The name of a variable that is set to the name of an SPL routine or external routine

The routine variable must have the data type CHAR, VARCHAR, NCHAR, or NVARCHAR. The routine name you assign to SPL variable must be non-null and the name of an existing routine.

Identifier, p. 1-966

Usage

The CALL statement invokes one of the following:

The CALL statement is identical in behavior to the EXECUTE PROCEDURE and EXECUTE FUNCTION statements, but you can only use CALL from within an SPL routine. You can use CALL in an ESQL/C program or with DB-Access, but only if you place the statement within an SPL routine executed by the program or DB-Access.

If you use CALL with a procedure name, you cannot specify a RETURNING clause. If you use CALL with a function name, you must specify a RETURNING clause.

Specifying Arguments

Specifying arguments is optional, whether you use CALL with a procedure or a function.

When you use CALL to execute a routine, you have the option of specifying parameter names for the arguments you pass to the routine. For example, each of the following examples is valid for a routine that has three parameters of VARCHAR type, named t, n, and d, in that order:

The syntax of specifying arguments is described in more detail in the Argument segment on page 1-828.

Receiving Input from the Called Routine

The RETURNING clause, used only with functions, specifies the data variable that receives the values the function returns. If you are calling a procedure, do not use the RETURNING clause.

The following example shows two routine calls.

One routine call is to a procedure (no_args), which expects no returned values. The second routine call is to a function (yes_args), which expects three returned values. The not_much() procedure declares three integer variables (i, j, and k) to receive the returned values from yes_args.

CONTINUE

Use the CONTINUE statement to start the next iteration of the innermost FOR, WHILE, or FOREACH loop.

Syntax

Usage

When you encounter a CONTINUE statement, the routine skips the rest of the statements in the innermost loop of the indicated type. Execution continues at the top of the loop with the next iteration. In the following example, the SPL function loop_skip inserts values 3 through 15 into the table testtable. The function also returns values 3 through 9 and 13 through 15 in the process. The function does not return the value 11, because it encounters the CONTINUE FOR statement. The CONTINUE FOR statement causes the function to skip the RETURN i WITH RESUME statement.

The CONTINUE statement generates errors if it cannot find the identified loop.

DEFINE

Use the DEFINE statement to declare variables that an SPL routine uses and to assign them data types.

Syntax

Element Purpose Restrictions Syntax

column name

The name of a column in the table.

The column must exist in the table by the time you run the SPL routine.

Identifier, p. 1-966

distinct type name

The name of a distinct type.

The distinct type must be defined in the database by the time you run the SPL routine.

Identifier, p. 1-966

opaque type name

The name of an opaque type.

The opaque type must be defined in the database by the time you run the SPL routine.

Identifier, p. 1-966

SPL variable

The name of the SPL variable that is being defined.

The name must be unique within the statement block.

Identifier, p. 1-966

Complex Data Type (Subset)

Element Purpose Restrictions Syntax

data type

The data type of the elements of a collection

The data type must match the data type of the elements of the collection the variable will contain.

The data type can be any data type except a SERIAL, SERIAL8, TEXT, BYTE, CLOB, or BLOB.

Identifier, p. 1-966

Default Value Clause

Usage

The DEFINE statement is not an executable statement. It must appear after the routine header and before any other statements.

If you define a local variable (by using DEFINE without the GLOBAL keyword), the scope of the variable is the statement block in which it is defined. You can use the variable anywhere within the statement block. You can also use the same variable name outside the statement block with a different definition.

If you define a variable with the GLOBAL keyword, the variable is global in scope and is available outside the statement block and to other routines.

SQL Data Type Subset

In defining variables, the SQL data type subset includes all the SQL data types except SERIAL, SERIAL8, TEXT, BYTE, CLOB, and BLOB.

Variables of INT data type hold data from SERIAL columns, and variables of INT8 data type hold data from SERIAL8 columns.

Referencing TEXT and BYTE Variables

The REFERENCES keyword lets you use TEXT and BYTE variables. TEXT and BYTE variables do not contain the actual data but are simply pointers to the data. The REFERENCES keyword is a reminder that the SPL variable is just a pointer. Use an SPL variables that references a TEXT or BYTE data type exactly as you would any other variable.

You cannot define a variable that references a CLOB or BLOB data type.

Declaring GLOBAL Variables

The GLOBAL keyword indicates that the variables that follow are available to other routines through the global environment. The global environment is the memory that is used by all the routines that run within a given DB-Access or SQL API session.

Routines that are running in the current session share global variables. Because the database server does not save global variables in the database, the global variables do not remain when the current session closes. The data types of global variables you use in your SPL routine must match the data types of variables in the global environment.

Databases do not share global variables. The database server does not share global variables with application development tools.

The first declaration of a global variable establishes the variable in the global environment. Subsequent global declarations simply bind the variable to the global environment and establish the value of the variable at that point. The following example shows two SPL procedures, proc1 and proc2. Each procedure has defined the global variable gl_out:

If proc1 is called first, gl_out is set to 13 and then incremented to 14. If proc2 is then called, it sees that the value of gl_out is already defined, so the default value of 23 is not applied. Then, proc2 assigns the existing value of 14 to tmp. If proc2 had been called first, gl_out would have been set to 23, and 23 would have been assigned to tmp. Later calls to proc1 would not apply the default of 13.

Providing Default Values

You can provide a literal value or a null value as the default for a global variable. You can also use a call to an SQL function to provide the default value. The following example uses the SITENAME function to provide a default value. It also defines a global BYTE variable.

SITENAME or DBSERVERNAME
If you use the value returned by SITENAME or DBSERVERNAME as the default, the variable must be a CHAR, VARCHAR, NCHAR, or NVARCHAR value of at least 18 characters.

USER
If you use USER as the default, the variable must be a CHAR, VARCHAR, NCHAR, or NVARCHAR value of at least 8 characters.

CURRENT
If you use CURRENT as the default, the variable must be a DATETIME value. If the YEAR TO FRACTION keyword has qualified your variable, you can use CURRENT without qualifiers. If your variable uses another set of qualifiers, you must provide the same qualifiers when you use CURRENT as the default value. The following example defines a DATETIME variable with qualifiers and uses CURRENT with matching qualifiers:

TODAY
If you use TODAY as the default, the variable must be a DATE value.

TEXT and BYTE
The only default value possible for a TEXT or BYTE variable is null. The following example defines a TEXT global variable that is called l_blob:

Declaring Local Variables

Most local variables (that is, nonglobal variables) do not allow defaults. The following example shows typical definitions of local variables:

Declaring Collection Variables

A variable of type COLLECTION, SET, MULTISET, and LIST is a collection variable and holds a collection fetched from the database. You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value.

A variable defined with the type COLLECTION is an untyped collection variable. An untyped collection variable is generic and can hold a collection of any type.

A variable defined with the type SET, MULTISET, or LIST is a typed collection variable. A typed collection variable can hold only a collection of its type.

You must define the elements of a typed collection variable as NOT NULL, as in the following examples:

Note that with variable c, both the INTEGER values in the SET and the SET values in the LIST are defined as NOT NULL.

You can define collection variables with nested complex types to hold matching nested complex type data. Any type or depth of nesting is allowed. You can nest row types within collection types, collection types within row types, collection types within collection types, s within collection and row types, and so on.

If you define a variable of COLLECTION type, the variable acquires varying type assignments if it is reused within the same statement block, as in the following example:

In this example, varA is a generic collection variable that changes its data type to the data type of the currently assigned collection. The first LET statement makes varA a SET variable. The second LET statement makes varA a LIST variable.

Declaring Row Variables

Row variables hold data from named or unnamed row types. You can define a generic row variable, a named row variable, or an unnamed row variable.

A generic row variable, defined with the ROW keyword, can hold data from any row type. A named row variable holds data from the specific named row type specified in the variable definition. The following statements show examples of generic row variables and named row variables:

A named row variable holds named row types of the same type in the variable definition.

To define a variable that will hold data stored in an unnamed row type, use the ROW keyword followed by the fields of the row type, as in:

Unnamed row types are type-checked only by structural equivalence. Two unnamed row types are considered equivalent if they have the same number of fields, and if the fields have the same type definitions. Therefore, you could fetch either of the following row types into the variable area defined above:

Row variables can have fields, just as row types have fields. To assign a value to a field of a row variable, use the SQL dot notation variableName.fieldName, followed by an expression, as in the following example:

When you assign a value to a row variable, you can use any allowed expression described in "Expression".

Declaring Opaque-Type Variables

Opaque type variables hold data retrieved from opaque types, which you create with the CREATE OPAQUE TYPE statement. An opaque type variable can only hold data of the opaque type on which it is defined.

The following example defines a variable of the opaque type point, which holds the x and y coordinates of a two-dimensional point:

Declaring Variables Like Columns

If you use the LIKE clause, the database server gives SPL variable the same data type as a column in a table, synonym, or view.

The data types of variables that are defined as database columns are resolved at runtime. Therefore, column and table do not need to exist at compile time.

Declaring Variables of Type PROCEDURE

The PROCEDURE type indicates that in the current scope, SPL variable is a call to an SPL routine or external routine. In this release of INFORMIX-Universal Server, the DEFINE statement does not have a FUNCTION keyword. Use the PROCEDURE keyword, whether you are calling a procedure or function.

Defining a variable of PROCEDURE type indicates that in the current statement scope, SPL variable is not a call to an SQL function or a system function. For example, the following statement defines length as an SPL routine, not as the SQL LENGTH function:

This definition disables the SQL LENGTH function within the scope of the statement block. You would use such a definition if you had already created an SPL routine or an external routine with the name length.

If you create a routine with the same name as an aggregate function (SUM, MAX, MIN, AVG, COUNT) or with the name extend, you must qualify the routine name with the owner name.

Declaring Variables for BYTE and TEXT Data

The keyword REFERENCES indicates that SPL variable is not a BYTE or TEXT value but a pointer to the BYTE or TEXT value. However, you can use the variable as though it holds the data.

The following example defines a local BYTE variable:

If you pass a variable of TEXT or BYTE data type to an SPL routine, the data is passed to the database server and stored in the root dbspace or dbspaces that the DBSPACETEMP environment variable specifies, if it is set. You do not need to know the location or name of the file that holds the data. BYTE or TEXT manipulation requires only the name of the BYTE or TEXT variable as it is defined in the routine.

You cannot declare a variable to hold or reference a CLOB or BLOB data type.

Redeclaring Variables

If you define the same variable twice within the same statement block, you receive an error. However, you can redefine a variable within a nested block, in which case it temporarily hides the outer declaration. The following example produces an error:

The database server allows the redeclaration in the following example. Within the nested statement block, n is a character variable. Outside the block, n is an integer variable.

EXIT

Use the EXIT statement to stop the execution of a FOR, WHILE, or FOREACH loop.

Syntax

Usage

The EXIT statement causes the innermost loop of the indicated type (FOR, WHILE, or FOREACH) to terminate. Execution resumes at the first statement outside the loop.

If the EXIT statement cannot find the identified loop, it fails.

If the EXIT statement is used outside all loops, it generates errors.

The following example uses an EXIT FOR statement. In the FOR loop, when j becomes 6, the IF condition i = 5 in the WHILE loop is true. The FOR loop stops executing, and the procedure continues at the next statement outside the FOR loop (in this case, the END PROCEDURE statement). In this example, the procedure ends when j equals 6.

FOR

Use the FOR statement to initiate a controlled (definite) loop when you want to guarantee termination of the loop. The FOR statement uses expressions or range operators to establish a finite number of iterations for a loop.

Syntax

Element Purpose Restrictions Syntax

expression

A numeric or character value against which variable name is compared to determine if the loop should be executed

The data type of expression must match the data type of variable name. You can use the output of a SELECT statement as an expression.

Expression, p. 1-880

increment expression

A positive or negative value by which variable name is incremented. Defaults to +1 or -1 depending on left expression and right expression.

The increment expression cannot evaluate to 0.

Expression, p. 1-880

left expression

The starting expression of a range

The value of left expression must match the data type of variable name. It must be either INT or SMALLINT.

Expression, p. 1-880

right expression

The ending expression in the range. The size of right expression relative to left expression determines if the range is stepped through positively or negatively.

The value of right expression must match the data type of variable name. It must be either INT or SMALLINT.

Expression, p. 1-880

variable name

The value of this variable determines how many times the loop executes.

You must have already defined this variable, and the variable must be valid within this statement block. If you are using variable name with a range of values and the TO keyword, you must define variable name explicitly as either INT or SMALLINT.

Identifier, p. 1-966

Usage

The database server computes all expressions before the FOR statement executes. If one or more of the expressions are variables, and their values change during the loop, the change has no effect on the iterations of the loop.

The FOR loop terminates when variable name takes on the values of each element in the expression list or range in succession or when it encounters an EXIT FOR statement.

The database server generates an error if an assignment within the body of the FOR statement attempts to modify the value of variable name.

Using the TO Keyword to Define a Range

The TO keyword implies a range operator. The range is defined by left expression and right expression, and the STEP increment expression option implicitly sets the number of increments. If you use the TO keyword, variable name must be an INT or SMALLINT data type. The following example shows two equivalent FOR statements. Each uses the TO keyword to define a range. The first statement uses the IN keyword, and the second statement uses an equal sign (=). Each statement causes the loop to execute five times.

If you omit the STEP option, the database server gives increment expression the value of -1 if right expression is less than left expression, or +1 if right expression is more than left expression. If increment expression is specified, it must be negative if right expression is less than left expression, or positive if right expression is more than left expression. The two statements in the following example are equivalent. In the first statement, the STEP increment is explicit. In the second statement, the STEP increment is implicitly 1.

The database server initializes the value of variable name to the value of left expression. In subsequent iterations, the server adds increment expression to the value of variable name and checks increment expression to determine whether the value of variable name is still between left expression and right expression. If so, the next iteration occurs. Otherwise, an exit from the loop takes place. Or, if you specify another range, the variable takes on the value of the first element in the next range.

Specifying Two or More Ranges in a Single FOR Statement
The following example shows a statement that traverses a loop forward and backward and uses different increment values for each direction:

Using an Expression List as the Range

The database server initializes the value of variable name to the value of the first expression specified. In subsequent iterations, variable name takes on the value of the next expression. When the server has evaluated the last expression in the list and used it, the loop stops.

The expressions in the IN list do not have to be numeric values, as long as you do not use range operators in the IN list. The following example uses a character expression list:

The following FOR statement shows the use of a numeric expression list:

Mixing Range and Expression Lists in the Same FOR Statement

If variable name is an INT or SMALLINT value, you can mix ranges and expression lists in the same FOR statement. The following example shows a mixture that uses an integer variable. Values in the expression list include the value that is returned from a SELECT statement, a sum of an integer variable and a constant, the values that are returned from an SPL procedure named p_get_int, and integer constants.

FOREACH

Use a FOREACH loop to select and handle a set of rows or a collection.

Syntax

Element Purpose Restrictions Syntax

cursor name

An identifier that you supply as a name for the FOREACH loop

Each cursor name within a routine must be unique.

Identifier, p. 1-966

data variable

The name of an SPL variable in the calling routine that will receive the value or values the called function returns

The data type of variable name must be appropriate for the value that is being returned.

Identifier, p. 1-966

routine variable

The name of an SPL variable in the calling routine that contains the name of a routine to be executed

The data type of routine variable must be CHAR, VARCHAR, NCHAR, NVARCHAR.

Identifier, p. 1-966

Usage

A FOREACH loop is the procedural equivalent of using a cursor. When Universal Server executes a FOREACH statement, it takes the following actions:

    1. It declares and implicitly opens a cursor.

    2. It obtains the first row, the first collection element, or the first set of return values (depending upon the syntax of your FOREACH statement).

    3. It assigns each variable in the variable list the corresponding value from the active set that the SELECT statement or the called routine creates.

    4. It executes the statement block.

    5. It fetches the next row, the next collection element, or the next set of return values, and it repeats steps 3 and 4.

    6. It terminates the loop when it finds no more rows, the end of the collection, or the last set of return values. It closes the implicit cursor when the loop terminates.

Because the statement block can contain additional FOREACH statements, you can nest cursors. No limit exists to the number of cursors that can be nested.

An SPL routine that returns more than one row, collection element, or set of values is called a cursor routine. An SPL routine that returns only one row or value is a noncursor routine.

The following SPL procedure illustrates the three types of FOREACH statements: with a SELECT...INTO clause, with an explicitly named cursor, and with a procedure call:

A select cursor is closed when any of the following situations occur:

Using a SELECT...INTO Statement

With an ordinary cursor that fetches a set of rows or values, you can use a SELECT ... INTO statement. With an ordinary cursor, SELECT ... INTO can also include the UNION and ORDER BY clauses, but it cannot include the INTO TEMP clause. The syntax of a SELECT statement is shown on page 1-596.

The type and count of each variable in the variable list must match each value that the SELECT...INTO statement returns.

Using Hold Cursors

The WITH HOLD keyword specifies that the cursor should remain open when a transaction closes (that is, is committed or rolled back).

Updating or Deleting Rows Identified by Cursor Name

Use the WHERE CURRENT OF cursor name clause to update or delete the current row of cursor name.

Using Collection Variables

The FOREACH statement allows you to declare a cursor for an SPL collection variable. Such a cursor is called a collection cursor. You use a collection variable to access the elements of a collection (SET, MULTISET, LIST) column. Use a cursor when you want to access one or more elements in a collection variable.

Tip: To access only one element of a collection variable, you do not need to declare a cursor. For information on how to select a single element, see "Selecting From a Collection Variable". For information on how to insert a single element, see "Inserting Into a Collection Variable".
If you are using a collection cursor to fetch individual elements from a collection variable, you must use a restricted form of the SELECT statement called a collection query. The collection query has the following restrictions:

The following excerpt from an SPL routine shows a collection query within a FOREACH loop:

In this example, the SELECT statement within the FOREACH loop is the collection query. The statement selects one element at a time from the collection variable b into the element variable a.

In the collection query, the select field list is an asterisk, because the collection variable b contains a collection of built-in types. The variable b is used with the TABLE keyword as a Collection Derived Table. For more information on using a Collection Derived Table, see page 1-831.

The next example shows a collection query that uses a list of row type fields in its select field list.

In this example, the collection variable employees contains a collection of row types. Each row type contains the fields name and salary. The collection query selects one name and salary combination at a time, placing name into n and salary into s. The AS keyword names e as an alias for the collection derived table employees. The alias exists as long as the SELECT statement executes.

To update an element of a collection, you must first declare a cursor with the FOREACH statement. Then, within the FOREACH loop, select elements one at a time from the collection variable, using the collection variable as a Collection Derived Table in a SELECT query. For more information on selecting from a collection variable, see the SELECT statement on page 1-596.

When the cursor is positioned on the element to be updated, you can use the WHERE CURRENT OF clause, as follows:

Calling a Routine in the FOREACH Loop

In general, use the following guidelines for calling another routine from an SPL routine:

Important: Universal Server allows you to use an EXECUTE PROCEDURE statement to execute SPL functions (routines that were formerly called stored procedures that return a value). However, Informix recommends that you use the EXECUTE PROCEDURE statement only with procedures and the EXECUTE FUNCTION statement only with functions.
If you use EXECUTE PROCEDURE, Universal Server looks first for a procedure of the name you specify. If it finds the procedure, the server executes it. If Universal Server does not find the procedure, it looks for a function of the same name to execute. If the server finds neither a function nor a procedure, it issues an error message.

If you use EXECUTE FUNCTION, Universal Server looks for a function of the name you specify. If it does not find a function of that name, the server issues an error message.

A called function can return zero or more values or rows. The type and count of each variable in the variable list must match each value that the function returns.

IF

Use an IF statement to create a branch within an SPL routine.

Syntax

Usage

The condition that the IF clause states is evaluated. If the result is true, the statements that follow the THEN keyword execute. If the result is false, and an ELIF clause exists, the statements that follow the ELIF clause execute. If no ELIF clause exists, or if the condition in the ELIF clause is not true, the statements that follow the ELIF keyword execute.

In the following example, the SPL function uses an IF statement with both an ELIF clause and an ELSE clause. The IF statement compares two strings and displays a 1 to indicate that the first string comes before the second string alphabetically, or a -1 if the first string comes after the second string alphabetically. If the strings are the same, a 0 is returned.

The ELIF Clause

Use the ELIF clause to specify one or more additional conditions to evaluate.

If you specify an ELIF clause, and the IF condition is false, the ELIF condition is evaluated. If the ELIF condition is true, the statements that follow the ELIF clause execute.

The ELSE Clause

The ELSE clause executes if no true previous condition exists in the IF clause or any of the ELIF clauses.

Conditions in an IF Statement

Conditions in an IF statement are evaluated in the same way as conditions in a WHILE statement.

If any expression that the condition contains evaluates to null, the condition automatically becomes untrue. Consider the following points:

    1. If the expression x evaluates to null, then x is not true by definition. Furthermore, not(x) is also not true.

    2. IS NULL is the sole operator that can yield true for x. That is, x IS NULL is true, and x IS NOT NULL is not true.

An expression within the condition that has an UNKNOWN value (due to the use of an uninitialized variable) causes an immediate error. The statement terminates and raises an exception.

IF Statement List

Subset of SQL Statements Allowed in an IF Statement
You can use any SQL statement in the statement block except the ones in the following list.

ALLOCATE DESCRIPTOR

GET DESCRIPTOR

CHECK TABLE

GET DIAGNOSTICS

CLOSE DATABASE

INFO

CONNECT

LOAD

CREATE DATABASE

OPEN

CREATE PROCEDURE

OUTPUT

DATABASE

PREPARE

DEALLOCATE DESCRIPTOR

PUT

DECLARE

REPAIR TABLE

DESCRIBE

ROLLFORWARD DATABASE

DISCONNECT

SET CONNECTION

EXECUTE

SET DESCRIPTOR

EXECUTE IMMEDIATE

START DATABASE

FETCH

UNLOAD

FLUSH

WHENEVER

FREE

You can use a SELECT statement only if you use the INTO TEMP clause to put the results of the SELECT statement into a temporary table.

LET

Use the LET statement to assign values to variables or to call a function from an SPL routine and assign the return value or values to variables.

Syntax

Element Purpose Restrictions Syntax

SPL variable

An SPL variable that receives the value the function returns or is set to the result of the expression

The SPL variable must be defined in the routine and must be valid in the statement block.

Identifier, p. 1-966

Usage

If you assign a value to a single variable, you make a simple assignment. If you assign values to two or more variables, you make a compound assignment.

You can also assign the value of an expression to a variable. At runtime, the value of the SPL expression is computed first. The resulting value is cast to the data type of variable, if possible, and the assignment occurs. If conversion is not possible, an error occurs, and the value of variable name is undefined.

A compound assignment assigns multiple expressions to multiple variables. The data types of expressions in the expression list does not need to match the data types of the corresponding variables in the variable list, because the database server automatically converts the data types. (For a detailed discussion of casting, see the Informix Guide to SQL: Reference.)

The following example shows several LET statements that assign values to SPL variables:

You cannot use multiple values to operate on other values. For example, the following statement is illegal:

Using a SELECT Statement in a LET Statement

The examples in this section use a SELECT statement within a LET statement. You can use a SELECT statement to assign values to one or more variables on the left side of the = operator, as the following examples show:

You cannot use a SELECT statement to make multiple values operate on other values. The following example is illegal:

Because a LET statement is equivalent to a SELECT...INTO statement, the two statements in the following example have the same results, a=c and b=d:

If the SELECT statement returns more than one row, you must enclose the SELECT statement in a FOREACH loop For more information on FOREACH, see page 2-27.

Calling a Function in a LET Statement

You can call an SPL function or an external function in a LET statement and assign the returned value or values to variables. You must specify all the necessary arguments to the function unless the function's arguments have default values.

If you name one of the parameters in the called function, with syntax such as name = 'smith', you must name all the parameters.

The named variable receives the returned value from a function call. A function can return more than one value into a list of variable names. However, you must enclose a function that returns more than one value in a FOREACH loop.

The following example shows several LET statements. The first two are valid LET statements that contain function calls. The third LET statement is not legal, because it tries to add the output of two functions and then assign the sum to two variables, a and b. You can easily split this LET statement into two legal LET statements.

A function called in a LET statement can have an argument of COLLECTION, SET, MULTISET, or LIST. COLLECTION is a generic collection data type that includes SET, MULTISET, and LIST collection types.

You can then assign the value returned by the function to a variable, for example:

In the first statement, the SPL function function1 accepts collection1 (that is, any collection data type) as an argument and returns its value to the variable d. In the second statement, the SPL function function2 accepts set1 as an argument and returns a value to the variable a.

ON EXCEPTION

Use the ON EXCEPTION statement to specify the actions that are taken for a particular error or a set of errors.

Syntax

Element Purpose Restrictions Syntax

error data variable

An SPL variable that contains a string returned by an SQL error or a user-defined exception

The variable must be a character data type to receive the error information. It must be valid in the current statement block.

Identifier, p. 1-966

error number

An SQL error number, or an error number created by a RAISE EXCEPTION statement, that is to be trapped

The error number must be of integer data type. It must be valid in the current statement block.

Literal number, p. 1-1001

ISAM error variable

A variable that receives the ISAM error number of the exception raised

The error variable must be of integer data type. It must be valid in the current statement block.

Identifier, p. 1-966

SQL error variable

A variable that receives the SQL error number of the exception raised

The error variable must be a character data type. It must be valid in the current statement block.

Identifier, p. 1-966

Usage

The ON EXCEPTION statement, together with the RAISE EXCEPTION statement, provides an error-trapping and error-recovery mechanism for SPL. The ON EXCEPTION statement defines a list of errors that are to be trapped as the SPL routine executes and specifies the action (within the statement block) to take when the trap is triggered. If the IN clause is omitted, all errors are trapped.

You can use more than one ON EXCEPTION statement within a given statement block.

The scope of an ON EXCEPTION statement is the statement block that follows the ON EXCEPTION statement, all the statement blocks that are nested within that following statement block, and all the statement blocks that follow the ON EXCEPTION statement.

The exceptions that are trapped can be either system- or user-defined.

When an exception is trapped, the error status is cleared.

If you specify a variable to receive an ISAM error, but no accompanying ISAM error exists, a zero returns to the variable. If you specify a variable to receive the returned error text, but none exists, an empty string goes into the variable.

Placement of the ON EXCEPTION Statement

ON EXCEPTION is a declarative statement, not an executable statement. For this reason, you must use the ON EXCEPTION statement before any executable statement and after any DEFINE statement in an SPL routine.

The following example shows the correct placement of an ON EXCEPTION statement. Use an ON EXCEPTION statement after the DEFINE statement and before the body of the routine.

The following SPL function inserts a set of values into a table. If the table does not exist, it is created, and the values are inserted. The SPL function also returns the total number of rows in the table after the insert occurs.

When an error occurs, the database server searches for the last declaration of the ON EXCEPTION statement, which traps the particular error code. The ON EXCEPTION statement can have the error number in the IN clause or have no IN clause. If the database server finds no pertinent ON EXCEPTION statement, the error code passes back to the caller (the routine, application, or interactive user), and execution aborts.

The following example uses two ON EXCEPTION statements with the same error number so that error code 691 can be trapped in two levels of nesting:

Using the IN Clause to Trap Specific Exceptions

A trap is triggered if either the SQL error code or the ISAM error code matches an exception code in the list of error numbers. The search through the list begins from the left and stops with the first match.

You can use a combination of an ON EXCEPTION statement without an IN clause and one or more ON EXCEPTION statements with an IN clause to set up default trapping. A summary of the sequence of statements in the following example would be: "Test for an error. If error -210, -211, or -212 occurs, take action A. If error -300 occurs, take action B. If any other error occurs, take action C." When an error occurs, the database server searches for the last declaration of the ON EXCEPTION statement that traps the particular error code.

Receiving Error Information in the SET Clause

If you use the SET clause, when an exception occurs, the SQL error code and (optionally) the ISAM error code are inserted into the variables that are specified in the SET clause. If you provided an error data variable, any error text that the database server returns is put into the error data variable. Error text includes information such as the offending table or column name.

Forcing the Routine to Continue

The example on page 2-45 uses the WITH RESUME keyword to indicate that after the statement block in the ON EXCEPTION statement executes, execution is to continue at the LET x = SELECT COUNT(*) FROM emp_list statement, which is the line following the line that raised the error. For this routine, the result is that the count of salespeople names occurs even if the error occurred.

Continuing Execution After an Exception Occurs

If you do not include the WITH RESUME keyword in your ON EXCEPTION statement, the next statement that executes after an exception occurs depends on the placement of the ON EXCEPTION statement, as the following scenarios describe:

Errors Within the ON EXCEPTION Statement Block

To prevent an infinite loop, if an error occurs during execution of the statement block of an error trap, the search for another trap does not include the current trap.

RAISE EXCEPTION

Use the RAISE EXCEPTION statement to simulate the generation of an error.

Syntax

Element Purpose Restrictions Syntax

error text variable

An SPL variable that contains the error text

The SPL variable must be a character data type and must be valid in the statement block.

Identifier, p. 1-966

ISAM error

A variable or expression that represents an ISAM error number. The default value is 0.

The variable or expression must evaluate to a SMALLINT value. You can place a minus sign before the error number.

Expression, p. 1-880

SQL error

A variable or expression that represents an SQL error number

The variable or expression must evaluate to a SMALLINT value. You can place a minus sign before the error number.

Expression, p. 1-880

Usage

Use the RAISE EXCEPTION statement to simulate an error. An ON EXCEPTION statement can trap the generated error.

If you omit the ISAM error parameter, the database server sets the ISAM error code to zero when the exception is raised. If you want to use the error text variable parameter but not specify a value for ISAM error, you can specify 0 as the value of ISAM error.

For example, the following statement raises the error number -9999 and returns the stated text:

The statement can raise either system-generated exceptions or user-generated exceptions.

In the following example, a negative value for a raises exception 9999. The code should contain an ON EXCEPTION statement that traps for an exception of 9999.

See the ON EXCEPTION statement for more information about the scope and compatibility of exceptions.

RETURN

Use the RETURN statement to designate the values that the routine returns to the calling module.

Syntax

Usage

The RETURN statement returns values to the calling module. An SPL routine that returns one or more values is called an SPL function.

All the RETURN statements in an SPL function must be consistent with the RETURNING clause of the CREATE FUNCTION statement, which defines the function. The number and data type of values in the RETURN statement, if any, must match in number and data type the data types that are listed in the RETURNING clause of the CREATE FUNCTION statement. You can choose to return no values even if you specify one or more values in the RETURNING clause. If you use a RETURN statement without any expressions, but the calling routine or program expects one or more return values, it is equivalent to returning the expected number of null values to the calling program.

In the following example, the SPL function includes two acceptable RETURN statements. A program that calls this function should check if no values are returned and act accordingly.

A RETURN statement without any expressions exits only if the SPL function is declared not to return values; otherwise it returns nulls.

In an SPL program, you can use an external function as an expression in a RETURN statement provided that the external function is not an iterator function. An iterator function is an external function that returns one or more rows of data and therefore requires a cursor to execute.

The WITH RESUME Keyword

If you use the WITH RESUME keyword after the RETURN statement executes, the next invocation of the SPL function (upon the next FETCH or FOREACH statement) starts from the statement that follows the RETURN statement. If a function executes a RETURN WITH RESUME statement, the calling routine or program must call the function within a FOREACH loop.

ESQL
If an SPL routine executes a RETURN WITH RESUME statement, a FETCH statement in an application that is written in an SQL API can call it.

The following example shows a cursor routine that another routine can call. After the RETURN i WITH RESUME statement returns each value to the calling routine or program, the next line of sequence() executes the next time sequence() is called. If backwards equals 0, no value is returned to the calling routine or program, and execution of sequence stops.

SYSTEM

Use the SYSTEM statement to make an operating-system command run from within an SPL routine.

Syntax

Element Purpose Restrictions Syntax

expression

Any expression that is a user-executable operating-system command

You cannot specify that the command run in the background.

Operating-system dependent

SPL variable

An SPL variable that contains a valid operating-system command

The SPL variable must be of CHAR, VARCHAR, NCHAR, NVARCHAR, or CHARACTER VARYING data type,

Identifier, p. 1-966

Usage

If the supplied expression is not a character expression, expression is converted to a character expression before the operating-system command is made. The complete character expression passes to the operating system and executes as an operating-system command.

The operating-system command that the SYSTEM statement specifies cannot run in the background. The database server waits for the operating system to complete execution of the command before it continues to the next statement in the SPL routine.

Your SPL routine cannot use a value or values that the command returns.

If the operating-system command fails (that is, if the operating system returns a nonzero status for the command), an exception is raised that contains the returned operating-system status as the ISAM error code and an appropriate SQL error code.

In routines that contain SYSTEM statements, the operating-system command runs with the permissions of the user who is executing the routine.

Specifying Environment Variables in SYSTEM Statements

When the operating-system command that SYSTEM specifies is executed, no guarantee exists that the environment variables that the user application set are passed to the operating system. To ensure that the environment variables that the application set are carried forward to the operating system, enter a SYSTEM command that sets the environment variables before you enter the SYSTEM command that causes the operating-system command to execute.

For information on the operating-system commands that set environment variables, see Chapter 3 of the Informix Guide to SQL: Reference.

Examples of the SYSTEM Statement in SPL Routines

The following example shows the use of a SYSTEM statement within an SPL routine. The SYSTEM statement in this example causes the operating system to send a mail message to the system administrator.

You can use a double-pipe symbol (||) to concatenate expressions with a SYSTEM statement, as the following example shows:

TRACE

Use the TRACE statement to control the generation of debugging output.

Syntax

Usage

The TRACE statement generates output that is sent to the file that the SET DEBUG FILE TO statement specifies.

Tracing prints the current values of the following items:

The output of each executed TRACE statement appears on a separate line.

If you use the TRACE statement before you specify a DEBUG file to contain the output, an error is generated.

Any routine the SPL routine calls inherit the trace state. That is, a called routine assumes the same trace state (ON, OFF, or PROCEDURE) as the calling routine. The called routine can set its own trace state, but that state is not passed back to the calling routine.

A routine that is executed on a remote database server does not inherit the trace state.

TRACE ON

If you specify the keyword ON, all statements are traced. The values of variables (in expressions or otherwise) are printed before they are used. To turn tracing ON implies tracing both routine calls and statements in the body of the routine.

TRACE OFF

If you specify the keyword OFF, all tracing is turned off.

TRACE PROCEDURE

If you specify the keyword PROCEDURE, only the routine calls and return values, but not the body of the routine, are traced.

The TRACE statement does not have ROUTINE or FUNCTION keywords. Therefore, use the TRACE PROCEDURE keywords even if the SPL routine you want to trace is a function.

Printing Expressions

You can use the TRACE statement with a quoted string or an expression to display values or comments in the output file. If the expression is not a literal expression, the expression is evaluated before it is written to the output file.

You can use the TRACE statement with an expression even if you used a TRACE OFF statement earlier in a routine. However, you must first use the SET DEBUG statement to establish a trace-output file.

The following example uses a TRACE statement with an expression after it uses a TRACE OFF statement:

The following example shows additional TRACE statements:

Looking at the Traced Output

To see the traced output, use an editor or utility to display or read the contents of the file.

WHILE

Use the WHILE statement to establish an indefinite loop within an SPL routine.

Syntax

Usage

The condition is evaluated once at the beginning of the loop, and subsequently at the beginning of each iteration. The statement block is executed as long as the condition remains true. The loop terminates when the condition evaluates to not true.

If any expression within the condition evaluates to null, the condition automatically becomes not true unless you are explicitly testing for the IS NULL condition.

If an expression within the condition has an unknown value because it references uninitialized SPL variables, an immediate error results. In this case, the loop terminates, and an exception is raised.




Informix Guide to SQL: Syntax, version 9.1
Copyright © 1998, Informix Software, Inc. All rights reserved.