INFORMIX
Informix-ESQL/C Programmer's Manual
Chapter 11: Exception Handling
Home Contents Index Master Index New Book

Exception Handling with SQLSTATE

Informix recommends that you obtain diagnostic information about SQL statements with the SQLSTATE variable and the GET DIAGNOSTICS statement.

Important: SQLSTATE is a more effective way to detect and handle error messages than the SQLCODE variable because SQLSTATE supports multiple exceptions. SQLSTATE is also more portable because it conforms to ANSI and X/Open standards. ESQL/C supports the sqlca structure and SQLCODE for backward compatibility and for Informix-specific exceptions. (For more information, see page 11-27.)
After the database server executes an SQL statement, it sets SQLSTATE with a value that indicates the success or failure of the statement. From this value, your program can determine if it needs to perform further diagnostics. If SQLSTATE indicates a problem, you can use the GET DIAGNOSTICS statement to obtain more information.

This section describes how to use the SQLSTATE variable and the GET DIAGNOSTICS statement to perform exception handling. It describes the following topics:

Using GET DIAGNOSTICS

This section briefly summarizes how to use the GET DIAGNOSTICS statement within an ESQL/C program. For a full description of the GET DIAGNOSTICS statement, refer to the Informix Guide to SQL: Syntax.

The GET DIAGNOSTICS statement returns information that is held in the fields of the diagnostics area. The diagnostics area is an internal structure that the database server updates after it executes an SQL statement. Each application has one diagnostics area. Although GET DIAGNOSTICS accesses the diagnostics area, it never changes the contents of this area.

To access a field in the diagnostics area, supply a host variable to hold the value and the field keyword to specify the field that you want to access:

Make sure that the data types of the host variable and the diagnostics field are compatible.

The fields of the diagnostics area fall into two categories:

Statement Information

The GET DIAGNOSTICS statement returns information about the most-recently executed SQL statement. This form of the GET DIAGNOSTICS statement has the following general syntax:

Figure 11-1 summarizes the statement_fields of the diagnostics area.

Figure 11-1
Statement Information from the GET DIAGNOSTICS Statement

Field-Name Keyword ESQL/C Data Type Description

NUMBER

int

This field holds the number of exceptions that the diagnostics area contains for the most-recently executed SQL statement. NUMBER is in the range of 1 to 35,000. Even when an SQL statement is successful, the diagnostics area contains one exception.

MORE

char[2]

This field holds either an N or a Y (plus a null terminator). An N character indicates that the diagnostics area contains all of the available exception information. A Y character indicates that the database server has detected more exceptions than it could store in the diagnostics area. At present, the database server always returns an N because the database server can store all exceptions.

ROW_COUNT

int

When the SQL statement is an INSERT, UPDATE, or DELETE, this field holds a numeric value that specifies the number of rows that the statement has inserted, updated, or deleted. ROW_COUNT is in the range of 0 to 999,999,999.

For any other SQL statement, the value of ROW_COUNT is undefined.

Figure 11-2 shows a GET DIAGNOSTICS statement that retrieves statement information for a CREATE TABLE statement into the host variables :exception_count and :overflow.

Figure 11-2
Using GET DIAGNOSTICS to Return Statement Information

Use the statement information to determine how many exceptions the most-recently executed SQL statement has generated. For more information, see "Multiple Exceptions".

For more information on the statement fields of the diagnostics area, see "The Statement Clause" in the GET DIAGNOSTICS statement in the Informix Guide to SQL: Syntax.

Exception Information

The GET DIAGNOSTICS statement also returns information about the exceptions that the most-recently executed SQL statement has generated. Each exception has an exception number. To obtain information about a particular exception, use the EXCEPTION clause of the GET DIAGNOSTICS statement, as follows:

The except_num argument can be a literal number or a host variable. An except_num of one (1) corresponds to the SQLSTATE value that the most-recently executed SQL statement sets. After this first exception, the order in which the database server fills the diagnostics area with exception values is not predetermined. For more information, see "Multiple Exceptions".

Figure 11-3 summarizes the exception_fields of the diagnostics area.

Figure 11-3
Exception Information from the GET DIAGNOSTICS Statement

(1 of 2)

Field Name Keyword ESQL/C Data Type Description

RETURNED_SQLSTATE

char[6]

This field holds the SQLSTATE value that describes the current exception. For information about the values of this field, see "Using the SQLSTATE Variable".

INFORMIX_SQLCODE

int

This field holds the Informix-specific status code. This code is also available in the global SQLCODE variable. For more information, see "Using the SQLCODE Variable".

CLASS_ORIGIN

char[255]

This field holds a variable-length character string that defines the source of the class portion of SQLSTATE. If Informix defines the class code, the value is "IX000". If the International Standards Organization (ISO) defines the class code, the value of CLASS_ORIGIN is "ISO 9075". If a user-defined routine has defined the message text of the exception, the value of CLASS_ORIGIN is "U0001".

SUBCLASS_ORIGIN

char[255]

This field holds a variable-length character string that contains the source of the subclass portion of SQLSTATE. If ISO defines the subclass, the value of SUBCLASS_ORIGIN is "ISO 9075". If Informix defines the subclass, the value is "IX000". If a user-defined routine has defined the message text of the exception, the value is "U0001".

MESSAGE_TEXT

char[8191]

This field holds a variable-length character string that contains the message text to describe this exception. This field can also contain the message text for any ISAM exceptions or a user-defined message from a user-defined routine.

MESSAGE_LENGTH

int

This field holds the number of characters that are in the text of the MESSAGE_TEXT string.

SERVER_NAME

char[255]

This field holds a variable-length character string that holds the name of the database server that is associated with the actions of a CONNECT or DATABASE statement. This field is blank when no current connection exists.

For more information about the SERVER_NAME field, see "Identifying an Explicit Connection".

CONNECTION_NAME

char[255]

This field holds a variable-length character string that holds the name of the connection that is associated with the actions of a CONNECT or DATABASE statement. This field is blank when no current connection exists. Otherwise, it contains the name of the last successfully established connection.

For more information about the CONNECTION_NAME field, see "Identifying an Explicit Connection".

Use the exception information to save detailed information about an exception. The code fragment in Figure 11-4 retrieves exception information on the first exception of a CREATE TABLE statement.

Figure 11-4
Example of Using GET DIAGNOSTICS to Return Exception Information

For more information on the exception fields, see the GET DIAGNOSTICS statement in the Informix Guide to SQL: Syntax.

Using the SQLSTATE Variable

SQLSTATE is a five-character string that the database server sets after it executes each SQL statement. The ESQL/C header file, sqlca.h, declares SQLSTATE as a global variable. Since the ESQL/C preprocessor automatically includes sqlca.h in an ESQL/C program, you do not need to declare SQLSTATE.

After the database server executes an SQL statement, the database server automatically updates the SQLSTATE variable as follows:

These updates to the SQLSTATE variable are equivalent to the execution of the following GET DIAGNOSTICS statement immediately after an SQL statement:

Tip: At runtime, ESQL/C automatically copies the value of the RETURNED_SQLSTATE field into the global SQLSTATE variable. Therefore, you do not usually need to access the RETURNED_SQLSTATE field directly. For more information, see "Multiple Exceptions".
The value in SQLSTATE is the status of the most-recently executed SQL statement before the GET DIAGNOSTICS statement executed. If the database server encounters an error when it executes the GET DIAGNOSTICS statement, it sets SQLSTATE to "IX000" and sets SQLCODE (and sqlca.sqlcode) to the value of the error number that corresponds to the error; the contents of the diagnostics area are undefined.

The SQLSTATE variable holds the ANSI-defined value for the exception. Each SQLSTATE value has an associated Informix-specific status code. You can obtain the value of this Informix-specific status code from either of the following:

The next two sections provide the following information about the format of the SQLSTATE value:

Class and Subclass Codes

To determine the success of an SQL statement, your ESQL/C program must be able to interpret the value in the SQLSTATE variable. SQLSTATE consists of a two-character class code and a three-character subclass code. In Figure 11-5, IX is the class code and 000 is the subclass code. The value "IX000" indicates an Informix-specific error.

Figure 11-5
The Structure of the SQLSTATE Code with the Value IX000

SQLSTATE can contain only digits and capital letters. The class code is unique but the subclass code is not. The meaning of the subclass code depends on the associated class code. The initial character of the class code indicates the source of the exception code, which Figure 11-6 summarizes.

Figure 11-6
Initial SQLSTATE Class-Code Values

Initial Class-Code Value Source of Exception Code Notes

0 to 4
A to H

X/Open and
ANSI/ISO

The associated subclass codes also begin in the range 0 to 4 or A to H.

5 to 9

Defined by the implementation

Subclass codes are also defined by the implementation.

I to Z

INFORMIX-Universal Server
INFORMIX-ESQL/C

Any of the Informix-specific error messages (those that the X/Open or ANSI/ISO reserved range does not support) have an SQLSTATE value of "IX000".

If a user-defined routine returns an error message that has been defined by the routine, the SQLSTATE value is "U0001".

List of SQLSTATE Class Codes

Figure 11-7 lists the valid SQLSTATE class and subclass values. This figure lists the first entry for each class code in bold.

Figure 11-7
Class and Subclass Codes for SQLSTATE

(1 of 4)

Class Subclass Meaning

00

000

Success

01

01

01

01

01

01

01

000

002

003

004

005

006

007

Success with warning

Disconnect error-transaction rolled back

Null value eliminated in set function

String data, right truncation

Insufficient item descriptor areas

Privilege not revoked

Privilege not granted

01

01

01

01

01

01

01

01

01

01

01

I01

I03

I04

I05

I06

I07

I08

I09

I10

I11

U01

Database has transactions

ANSI-compliant database selected

Database on any Database server other than INFORMIX-SE selected

Float to decimal conversion used

Informix extension to ANSI-compliant standard syntax

After a DESCRIBE, a prepared UPDATE/DELETE statement does not have a WHERE clause

An ANSI keyword has been used as cursor name

Number of items in select list is not equal to number of items in INTO list

Database server is running in secondary mode

DATASKIP feature is turned on

User-defined warning returned by a user-defined routine

02

000

No data found or End of data reached

07

07

07

07

07

07

07

07

07

000

001

002

003

004

005

006

008

009

Dynamic SQL error

USING clause does not match dynamic parameters

USING clause does not match target specifications

Cursor specification cannot be executed

USING clause is required for dynamic parameters

Prepared statement is not a cursor specification

Restricted data type attribute violation

Invalid descriptor count

Invalid descriptor index

08

08

08

08

08

08

08

08

000

001

002

003

004

006

007

S01

Connection exception

Database server rejected the connection

Connection name in use

Connection does not exist

Client unable to establish connection

Transaction rolled back

Transaction state unknown

Communication failure

0A

0A

000

001

Feature not supported

Multiple database server transactions

21

21

21

000

S01

S02

Cardinality violation

Insert value list does not match column list

Degree of derived table does not match column list

22

22

22

22

22

22

22

22

22

22

000

001

002

003

005

012

019

024

025

027

Data exception

String data, right truncation

Null value, no indicator parameter

Numeric value out of range

Error in assignment

Division by zero

Invalid escape character

Unterminated string

Invalid escape sequence

Data exception trim error

23

000

Integrity-constraint violation

24

000

Invalid cursor state

25

000

Invalid transaction state

2B

000

Dependent privilege descriptors still exist

2D

000

Invalid transaction termination

26

000

Invalid SQL statement identifier

2E

000

Invalid connection name

28

000

Invalid user-authorization specification

33

000

Invalid SQL descriptor name

34

000

Invalid cursor name

35

000

Invalid exception number

37

000

Syntax error or access violation in PREPARE or EXECUTE IMMEDIATE

3C

000

Duplicate cursor name

40

40

000

003

Transaction rollback

Statement completion unknown

42

000

Syntax error or access violation

S0

S0

S0

S0

S0

000

001

002

011

021

Invalid name

Base table or view table already exists

Base table not found

Index already exists

Column already exists

S1

001

Memory-allocation error message

IX

000

Informix reserved error message

U0

001

User-defined error returned by a user-defined routine

The ANSI or X/Open standards define all SQLSTATE values except the following:

For more information on non-standard error values, see "Runtime Errors in SQLSTATE". For more information on non-standard warning values, see "Warnings in SQLSTATE".

Checking for Exceptions with SQLSTATE

After an SQL statement executes, the SQLSTATE value can indicate one of the four conditions that Figure 11-8 shows.

Figure 11-8
Exceptions That SQLSTATE Returns

Exception Condition SQLSTATE Value

Success

"00000"

Success, but no rows found

"02000"

Success, but warnings generated

Class code = "01"

Subclass code = "000" to "006"
(for ANSI and X/Open warnings)

Subclass code = "I01" to "I11"
(for Informix-specific warnings)

Subclass code = "U01"
(for user-defined warnings)

Failure, runtime error generated

Class code > "02"
(for ANSI and X/Open errors)

Class code = "IX"
(for Informix-specific errors)

Class code = "U0"
(for user-defined errors)

For a general introduction to these four conditions, see "Types of Diagnostic Information". To determine the cause of an exception in SQLSTATE, use the GET DIAGNOSTICS statement.

To determine the cause of an exception in SQLSTATE

1. Use GET DIAGNOSTICS to obtain the statement information such as the number of exceptions that the database server has generated.

    2. For each exception, use the EXCEPTION clause of GET DIAGNOSTICS to obtain detailed information about the exception.

The following sections discuss how SQLSTATE indicates each condition.

Success in SQLSTATE

When the database server executes an SQL statement successfully, it sets SQLSTATE to "00000" (class = "00", subclass = "000"). To check for successful execution, your code needs to verify only the first two characters of SQLSTATE.

Tip: After a CONNECT, SET CONNECTION, DATABASE, CREATE DATABASE, or START DATABASE statement, the SQLSTATE variable has a class value of "01" and an Informix-specific subclass value to provide information about the database and connection. For more information, see Figure 11-10.
The getdiag sample program on page 11-57 uses the sqlstate_err() function to compare the first two characters of SQLSTATE with the string "00" to check for successful execution of an SQL statement. The sqlstate_exception() function shown in Figure 11-19 checks for a success in SQLSTATE with the system strncmp() function.

NOT FOUND in SQLSTATE

When a SELECT or FETCH statement encounters NOT FOUND (or END OF DATA), the database server sets SQLSTATE to "02000" (class = "02"). Figure 11-9 lists the conditions that cause SQL statements to yield NOT FOUND.

Figure 11-9
SQLSTATE Values That Are Set When SQL Statements Do Not Return Any Rows

(1 of 2)

SQL Statement That Generates the Indicated SQLSTATE Result Result for ANSI-Compliant Database Result for non-ANSI-Compliant Database

FETCH statement: the last qualifying row has already been returned (the end of data has been reached).

"02000"

"02000"

SELECT statement: no rows match the SELECT criteria.

"02000"

"02000"

DELETE and DELETE...WHERE statement (not part of multistatement PREPARE): no rows match the DELETE criteria.

"02000"

"00000"

INSERT INTO tablename SELECT statement (not part of multistatement PREPARE): no rows match the SELECT criteria.

"02000"

"00000"

SELECT... INTO TEMP statement (not part of multistatement PREPARE): no rows match the SELECT criteria.

"02000"

"00000"

UPDATE and UPDATE...WHERE statement (not part of multistatement PREPARE): no rows match the UPDATE criteria.

"02000"

"00000"

Figure 11-9 shows that the value that the NOT FOUND condition generates depends, in some cases, on whether the database is ANSI compliant.

To check for the NOT FOUND condition, your code needs to verify only
the class code of SQLSTATE. The subclass code is always "000". The
getdiag sample program on
page 11-57 uses the sqlstate_err() function to
perform exception handling. To check for a warning in an SQL statement, sqlstate_err() compares the first two characters of SQLSTATE with the
string "02".

Warnings in SQLSTATE

When the database server executes an SQL statement successfully, but encounters a warning condition, it sets the class code of SQLSTATE to "01". The subclass code then indicates the cause of the warning. This warning can be either of the following types:

    The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields of the diagnostics area have a value of "ISO 9075" to indicate ANSI or X/Open as the source of the warning.

    The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields of the diagnostics area have a value of "IX000" to indicate an Informix-specific exception as the source of the warning.

    The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields of the diagnostics area have a value of "U0001" to indicate a user-defined routine as the source of the warning.

Figure 11-10 lists the Informix-specific warning messages and the SQL statements and conditions that generate the warning.

Figure 11-10
SQL Statements That Set an Informix-Specific Warning for a Given Condition

(1 of 2)

Warning Value SQL Statement Warning Condition

"01I01"

CONNECT
CREATE DATABASE
DATABASE
SET CONNECTION

Your application opened a database that uses transactions.

"01I03"

CONNECT
CREATE DATABASE
DATABASE
SET CONNECTION

Your application opened an ANSI-compliant database.

"01I04"

CONNECT
CREATE DATABASE
DATABASE
SET CONNECTION

Your application opened a database that uses the Universal Server or OnLine database server.

"01I05"

CONNECT
CREATE DATABASE
DATABASE
SET CONNECTION

Your application opened a database that is on a host database server that requires float-to-decimal conversion for FLOAT columns (or smallfloat-to-decimal conversions for SMALLFLOAT columns).

"01I06"

All statements

The statement just executed contains an Informix extension to SQL (only when the DBANSIWARN environment variable is set).

"01I07"

PREPARE
DESCRIBE

A prepared UPDATE or DELETE statement has no WHERE clause. The operation will affect all rows of the table.

"01I09"

FETCH
SELECT...INTO
EXECUTE...INTO

The number of items in the select list does not equal the number of host variables in the INTO clause.

"01I10"

CONNECT
CREATE DATABASE
DATABASE
SET CONNECTION

The database server is currently running in secondary mode. The database server is a secondary server in a data-replication pair; therefore, the database server is available only for read operations.

"01I11"

Other statements

(when your application activates the DATASKIP feature)

A data fragment (a dbspace) has been skipped during query processing.

For a list of the ANSI and X/Open warning messages, see "List of SQLSTATE Class Codes".

To check for a warning, your code only needs to verify the first two characters of SQLSTATE. However, to identify the particular warning, you need to examine the subclass code. You might also want to use the GET DIAGNOSTICS statement to obtain the warning message from the MESSAGE_TEXT field.

For example, the block of code in Figure 11-11 determines what kind of database a CONNECT statement has opened.

Figure 11-11
Using SQLSTATE to Check for
Informix-Specific Warnings

The code fragment in Figure 11-11 checks SQLSTATE with the system strncmp() function. The getdiag sample program (page 11-57) uses the sqlstate_err() function to check the success of an SQL statement by comparing the first two characters of SQLSTATE with the string "01". For more information about the values of SQLSTATE that the CONNECT, CREATE DATABASE, DATABASE, and SET CONNECTION statements set, see "Determining Features of the Database Server".

Runtime Errors in SQLSTATE

When an SQL statement results in a runtime error, the database server stores a value in SQLSTATE whose class code is greater than "02". The actual class and subclass codes identify the particular error. Figure 11-7 lists the class and subclass codes for SQLSTATE. To retrieve the error message text, use the MESSAGE_TEXT field of the GET DIAGNOSTICS statement. The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields have a value of "ISO 9075" to indicate the source of the error.

If the SQL statement generates an error that the ANSI or X/Open standards do not support, SQLSTATE might contain either of the following values:

    The SQLCODE variable contains the Informix-specific error code, and the MESSAGE_TEXT field contains the error message text and any ISAM message text. The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields have a value of "IX000" to indicate the source of the error.

    The MESSAGE_TEXT field contains the error message text. The CLASS_ORIGIN and SUBCLASS_ORIGIN exception fields have a value of "U0001" to indicate the source of the error.

Multiple Exceptions

The database server can generate multiple exceptions for a single SQL statement. A significant advantage of the GET DIAGNOSTICS statement is its ability to report multiple exception conditions.

To find out how many exceptions the database server has reported for an SQL statement, retrieve the value of the NUMBER field from the statement information of the diagnostics area. The following GET DIAGNOSTICS statement retrieves the number of exceptions that the database server generated and stores the number in the :exception_num host variable.

Once you know the number of exceptions that occurred, you can initiate a loop to report each of them. Execute GET DIAGNOSTICS within this loop and use the number of exceptions to control the loop. Figure 11-12 illustrates one way to retrieve and report multiple exception conditions after an SQL statement.

Figure 11-12
Reporting Multiple Exception Conditions

Do not confuse the RETURNED_SQLSTATE value with the SQLSTATE global variable. The SQLSTATE variable provides a general status value for the most-recently executed SQL statement. The RETURNED_SQLSTATE value is associated with one particular exception that the database server has encountered. For the first exception, SQLSTATE and RETURNED_SQLSTATE have the same value. However, for multiple exceptions, you must access RETURNED_SQLSTATE for each exception.

To define a host variable in your application that receives the RETURNED_SQLSTATE value, you must define it as a character array with a length of six (five for the field plus one for the null terminator). You can assign this variable whatever name you wish.

The following statements define such a host variable and assign it the name sql_state:

A database system that is compliant with X/Open standards must report any X/Open exceptions before it reports any Informix-specific errors or warnings. Beyond this, however, the database server does not report the exceptions in any particular order. The getdiag sample program (page 11-57) includes the disp_sqlstate_err() function to display multiple exceptions.




Informix-ESQL/C Programmer's Manual, version 9.1
Copyright © 1998, Informix Software, Inc. All rights reserved.