Error Handling with the Whenever Statement
The syntax of the whenever statement is:
exec sql whenever condition action;
condition
Specifies the error condition. Valid error conditions are dbevent, sqlwarning, sqlerror, sqlmessage, and not found.
action
Specifies the action to be taken. Valid actions are continue, stop, goto a label, and call a C procedure.
For a detailed description of this statement, see the SQL Reference Guide.
In C, all labels and procedure names must be legal C identifiers, beginning with an alphabetic character or an underscore. If the label is an embedded SQL reserved word, specify it in quotes. The label targeted by the goto action must be in the scope of all subsequent embedded SQL statements until another whenever statement is encountered for the same action. This is necessary because the preprocessor may generate the C statement:
if (condition) goto label;
after an embedded SQL statement. If the scope of the label is invalid, the C compiler generates an error.
The same scope rules apply to procedure names used with the call action. The reserved procedure sqlprint, which prints errors or database procedure messages and then continues, is always in the scope of the program. When a whenever statement specifies a call as the action, the target procedure is called, and after its execution, control returns to the statement following the statement that caused the procedure to be called. Consequently, after handling the whenever condition in the called procedure, you may want to take some action, instead of merely issuing a C return statement. The C return statement causes the program to continue execution with the statement following the embedded SQL statement that generated the error.
You can also use user-defined handlers for error handling. For more information, see the SQL Reference Guide.
The following example demonstrates use of the whenever statement in the context of printing some values from the Employee table. The comments do not relate to the program but to the use of error handling.
Example: whenever statement usage
exec sql include sqlca;
Db_Test()
{
exec sql begin declare section;
short eno;
char ename[21];
char age;
exec sql end declare section;
exec sql declare empcsr cursor for
select eno, ename, age
from employee;
/*
** An error when opening the personnel database will
** cause the error to be printed and the program
** to abort.
*/
exec sql whenever sqlerror stop;
exec sql connect personnel;
/* Errors from here on will cause the program to
** clean up
*/
exec sql whenever sqlerror call Clean_Up;
exec sql open empcsr;
printf("Some values from the \"employee\" table.\n");
/*
** When no more rows are fetched, close the cursor
*/
exec sql whenever not found goto close_csr;
/*
** The last executable embedded SQL statement was an
** OPEN, so we know that the value of "sqlcode"
** cannot be SQLERROR or NOT FOUND.
*/
while (1) /* Loop is broken by NOT FOUND */
{
exec sql fetch empcsr
into :eno, :ename, :age;
/*
** This "printf" does not execute after the
** previous FETCH returns the NOT FOUND
** condition.
*/
printf("%d, %s, %d\n", eno, ename, age);
}
/*
** From this point in the file onwards, ignore all
** errors. Also turn off the NOT FOUND condition,
** for consistency
*/
exec sql whenever sqlerror continue;
exec sql whenever not found continue;
Close_Csr:
exec sql close empcsr;
exec sql disconnect;
}
/*
** Clean_Up: Error handling procedure (print error and disconnect).
*/
Clean_Up()
{
exec sql begin declare section;
char errmsg[101];
exec sql end declare section;
exec sql inquire_sql (:errmsg = ERRORTEXT);
printf("Aborting because of error:\n%s\n", errmsg);
exec sql disconnect;
exit(-1); /* Do not return to Db_Test */
}