SQL execution diagnostics
If an SQL statement execution fails, error description can be found in the
SQLCA.SQLCODE
, SQLSTATE
, STATUS
and
SQLERRMESSAGE
predefined registers.
Trapping SQL errors
By default, SQL errors stop program execution and display the error message to the standard output. Most SQL statements executed by a program should not return an error and thus do not require error trapping. However, in some cases, a program must keep the control when an SQL error occurs. For example, when connecting to the database, the user might enter an invalid password that will raise a login denied error. The program must trap such SQL connection error in order to return to the login dialog and let the user enter a new login and password.
WHENEVER ERROR
exception handler or with a
TRY
/ CATCH
block:-- WHENEVER ERROR handler
WHENEVER ERROR CONTINUE
INSERT INTO orders VALUES ( rec_ord. * )
IF SQLCA.SQLCODE = -75623 THEN
...
END IF
WHENEVER ERROR STOP -- restore the default
-- TRY/CATCH block
TRY
INSERT INTO orders VALUES ( rec_ord. * )
CATCH
IF SQLCA.SQLCODE = -75623 THEN
...
END IF
END TRY
Using SQLCA.SQLCODE
SQL error codes are provided in the SQLCA.SQLCODE
register. This register always contains an IBM® Informix® error code, even when
connected to a database that is different from IBM Informix.
STATUS
is the global error code register that can be set for any kind of error
(even non-SQL). When an SQL error occurs, both SQLCA.SQLCODE
and
STATUS
hold the SQL error code.
Use SQLCA.SQLCODE
for SQL error management, and use STATUS
to
detect errors with other language instructions.
When connecting to a database that is different from IBM
Informix, the database driver tries to convert the native
SQL error to an IBM Informix error which will be copied into the SQLCA.SQLCODE
and
STATUS
registers. If the native SQL error cannot be converted,
SQLCA.SQLCODE
and STATUS
will be set to -6372 (a general SQL error).
You can then check the native SQL error in SQLCA.SQLERRD[2]
. The native SQL error
code is always available in SQLCA.SQLERRD[2]
, even if it cannot be converted to an
IBM Informix
error.
Using SQLSTATE
SQLSTATE
is a register that contains an error code following ISO
standards. However, not all database servers support this standard.
Preferably use SQLSTATE
for
SQL error checking, as long as the target databases support this feature.
SQLSTATE
codes are defined by the ISO standards. However, not all
database types support this standard.Database Server Type | Supports SQLSTATE errors |
---|---|
IBM DB2® LUW (UNIX™) | Yes, since version 7.1 |
IBM Informix | Yes, since IDS 10 |
IBM Netezza® | Yes |
Microsoft™ SQL Server | Yes, since version 8 (2000) |
Oracle® MySQL | Yes |
Oracle Database Server | Not in version 10.2 |
PostgreSQL | Yes, since version 7.4 |
SAP® ASE | Yes |
SAP HANA® | Yes |
Centralize SQL error checking
SQL error identification sometimes requires complex code to check several RDBMS-specific error numbers. Therefore, it is strongly recommended that you centralize SQL error identification in a function. When needed, this allows you to write the RDBMS-specific code only once.
For maximum SQL portability, centralize SQL error checking in functions, to test either
SQLCA.SQLCODE
or SQLSTATE
, depending on the database
server type. Furthermore, consider defining error identifiers with constants:
CONSTANT SQLERR_INVALID_DATABASE = -1001,
SQLERR_INVALID_USER = -1002,
...
FUNCTION do_connect()
DEFINE uname, upswd VARCHAR(100)
WHILE TRUE
CALL login() RETURNING uname, upswd
TRY
CONNECT TO "stores" USER uname USING upswd
CATCH
CASE check_sql_error()
WHEN SQLERR_INVALID_DATABASE
DISPLAY SQLERRMESSAGE
EXIT PROGRAM 1 -- Fatal error: Stop!
WHEN SQLERR_INVALID_USER
ERROR "Invalid login, try again"
CONTINUE WHILE
END CASE
END TRY
EXIT WHILE
END WHILE
END FUNCTION
SQL error messages
SQLERRMESSAGE
is a register that contains the database-specific error
message. These messages are different for every database type.
Only use SQLERRMESSAGE
to
print or log SQL execution diagnostics.
SQL warnings
Some SQL instructions can produce SQL warnings. Unlike SQL errors, SQL warnings indicate a minor issue that can often be ignored. For example, when connecting to an IBM Informix database, a warning is returned to indicate that a database connection was opened. Another warning may also be returned if the database supports transactions. None of these facts are critical, but that information may help with program execution.
If an SQL warning is raised, SQLCA.SQLCODE
/ STATUS
remain
zero, and the program flow continues. To detect if an SQL warning has occurred, the SQLCA.SQLAWARN register must be
checked. SQLCA.SQLAWARN
is defined as a CHAR(7)
variable. If
SQLCA.SQLAWARN[1]
contains the W
letter, it means that the last
SQL instruction returned a warning. The other character positions
(SQLCA.SQLAWARN[2-8]
) may contain W
letters too, depending on the
database server type and the type of SQL instruction that was executed.
If SQLCA.SQLAWARN
is set, you can also check the SQLSTATE
and
SQLCA.SQLERRD[2]
registers to get more details about the warning. The
SQLERRMESSAGE
register might also contain the warning description.
SQLCA.SQLAWARN
register:
MAIN
DATABASE stores
DISPLAY "[", sqlca.sqlawarn, "]"
END MAIN
When connecting to an IBM Informix database with transactions, the program will display the following:
[WW W ]
WHENEVER WARNING
instruction, as shown in this
example:MAIN
DEFINE cust_name VARCHAR(50)
DATABASE stores
WHENEVER WARNING STOP
SELECT cust_lname, cust_address INTO cust_name
FROM customer WHERE cust_id = 101
WHENEVER WARNING CONTINUE
END MAIN
The SELECT
statement in the above example uses two columns in the select list,
while only one INTO
variable is provided. This is legal and does not raise an SQL
error. However, SQLCA.SQLAWARN
is set to indicate that the number of target
variables does not match the select-list items.
See also WHENEVER WARNING exception.
Display detailed debug information in case of internal driver error
If an unexpected problem happens within the database driver, it will return the error -6319 (indicating an internal error in the database driver). When this SQL error occurs, set the FGLSQLDEBUG environment variable to get more details about the internal error.
Determine the number of processed rows
SQL statements such as UPDATE
and DELETE
can affect zero, one
or several rows.
If you need to check how many rows are processed by an SQL statement, check the
SQLCA.SQLERRD[3]
register.
SQLCA.SQLCODE
and
SQLCA.SQLERRD[3]
registers are used to diagnose the execution of an
UPDATE
statement:TYPE t_country RECORD
c_code CHAR(5),
c_desc VARCHAR(50)
END RECORD
FUNCTION update_country_description(rec t_country) RETURNS INTEGER
UPDATE country SET desc = rec.c_desc WHERE code = rec.c_code
CASE
WHEN SQLCA.SQLCODE < 0
MESSAGE SFMT("SQL error:%1 [%2]", SQLCA.SQLCODE, SQLERRMESSAGE)
RETURN -2
WHEN SQLCA.SQLCODE == 0
IF SQLCA.SQLERRD[3] == 0 THEN
MESSAGE SFMT("No country was found with code: %1", rec.c_code)
RETURN -1
ELSE
MESSAGE SFMT("Updated country with code: %1", rec.c_code)
END IF
END CASE
RETURN 0
END FUNCTION
For more details see The SQLCA diagnostic record.