What if something goes wrong? Every env and dbc and stmt and
desc has a structure called the Diagnostics Area. The DBMS fills it with
information about what happened during the last function call. The diagnostics
area has one "header" and zero or more "status records". This partial
illustration shows only the most important fields:
-----------------------------------------
- SQL_DIAG_RETURNCODE | SQL_DIAG_NUMBER -
- --------------------+------------------
- - -1 | 00003 |
-----------------------------------------
-
- ----------------------------------------------------------------------
- - SQL_DIAG_SQLSTATE | SQL_DIAG_MESSAGE_TEXT | ... |
- ---------------------------------------------------------------------
- 1 - 23000 | Integrity Constraint Violation - constraint <X> | ... |
- 2 - 01003 | Warning - null value eliminated in set function | ... |
- 3 - 01008 | Warning - implicit zero-bit padding | ... |
- ---------------------------------------------------------------------
This diagram shows the diagnostics area of a stmt, just after this function
call:
sqlreturn = SQLExecDirect(
hstmt,"UPDATE T SET a=(SELECT MAX(b) FROM X),c=X'5'",SQL_NTS);
Looking at the header, we can see that the function failed because the
SQL_DIAG_RETURNCODE field is -1, which is SQL_ERROR (sqlreturn will
also equal -1). Also, from the fact that the header's SQL_DIAG_NUMBER field
is 3, we can see that there are three status records.
Looking at the status records, we can see that three different things went
wrong during the execution of the SQL statement. Two of them were merely
warnings ("completion conditions"). Probably the DBMS encountered these
conditions while it was setting up for the UPDATE, but it kept on going.
Then it hit a showstopper: an "exception condition". Although this "integrity
Constraint violation" error was the third condition encountered, it is the
first in order among the status records because an error's priority is higher
than a warning's.
The SQL_DIAG_SQLSTATE field contains a code for a reasonably precise
categorization of the condition. This code is called the status code, or
SQLSTATE value (because the DBMS always puts the status code in the
SQL_DIAG_SQLSTATE field). You can see what the SQLSTATE codes mean by
looking at the chart of codes at the end of this chapter.
The SQL_DIAG_MESSAGE_TEXT field might be the sort of text you'd like to
send to the user's screen for this condition. Unlike the status code, the
message text is implementation-dependent: it's not standardized. It might be
internationalized; that is, it might not be in English. So there is a lot more
information here than a mere "failed" return code. And there are many more
fields than the ones in the picture, which can help you get an even more
precise diagnosis of "why didn't the SQLExecDirect function work". In order
to retrieve the diagnostics-area information into your application program, you
need to use one of these CLI functions:
SQLGetDiagField-- You'll need this function to get any field from any part of the diagnostics area, one field at a time.SQLGetDiagRec-- With this function, you can pick up several of the most popular fields, includingSQL_DIAG_SQLSTATEandSQL_DIAG_MESSAGE_TEXT.SQLError-- You'll want to know about this slightly obsolescent function because it appears frequently in legacy code.- SQLRowCount -- This isn't exactly a diagnostics function, but it does get a
value from a particular diagnostics-area field:
SQL_DIAG_ROW_COUNT.
The descriptions of these four functions follow.
Table of Contents
Function Prototype:
SQLRETURN SQLGetDiagField(
SQLSMALLINT HandleType, /* 16-bit input */
SQLINTEGER Handle, /* 32-bit input */
SQLSMALLINT RecordNumber, /* 16-bit input */
SQLSMALLINT DiagIdentifier, /* 16-bit input */
SQLPOINTER DiagInfo, /* ANY* output */
SQLSMALLINT BufferLength, /* 16-bit input */
SQLSMALLINT *StringLength /* 16-bit output */
);
Job: Get one piece of information from a diagnostics area, for example, the
SQLSTATE of a warning that was posted for the last function call.
There are 50 variations of SQLGetDiagField, depending on the diagnostics
field whose value you want to examine. Here's an example and short description
of each variation; each uses these shorthands:
- The words "last call" mean "the last function called using this handle, other
than
SQLGetDiagFieldorSQLGetDiagRecorSQLError". The principle (anti-Heisenbergian) here is that the act of observation must not affect the thing observed, so the diagnostics routines don't themselves post diagnostics information. - The punctuation ...,..., at the beginning of each function example's
parameter list means "assume there is a valid handle type and handle here".
The
HandleTypeparameter must beSQL_HANDLE_ENV,SQL_HANDLE_DBC,SQL_HANDLE_STMTorSQL_HANDLE_DESC. The corresponding Handle parameter must be ahenvorhdbcorhstmtorhdesc. Where the only acceptable value is ahstmt, the parameter list starts withSQL_HANDLE_STMT,hstmt. - The name used for the
DiagInfoparameter gives an indication of the <data type> thatSQLGetDiagFieldreturns: smallint, integer or character string. - The word
NULLin a function's argument list means "doesn't matter". None of the diagnostics fields containNULLin the SQL sense. - The four-digit number at the beginning of each paragraph is the code for the
DiagIdentifierparameter. We have done the same thing here that we did in our chapter on thedescfunctions; namely, treating the name of thesqlcli.hcode constant as the name of the field.
The nine "Header" fields in a diagnostics area occur only once. It does not
matter what you pass for the RecordNumber parameter.
0001SQLGetDiagField(...,...,NULL,SQL_DIAG_RETURNCODE,&smallint,NULL,NULL);
This field gives you the last call's return code:
SQL_SUCCESS,SQL_ERROR,SQL_SUCCESS_WITH_INFO,SQL_NEED_DATAorSQL_NO_DATA. You need to call this if you failed to save the return code in ansqlreturnvariable.0002SQLGetDiagField(...,...,NULL,SQL_DIAG_NUMBER,&integer,NULL,NULL);
This field gives you the number of Status Records (exception or completion conditions) that the DBMS generated for the last call. The value will be zero if the return code is
SQL_SUCCESS, and will probably (but not certainly) be zero if the return code isSQL_NO_DATA.0003SQLGetDiagField( SQL_HANDLE_STMT,hstmt,NULL,SQL_DIAG_ROW_COUNT,&integer,NULL,NULL);
If the last call was
SQLExecDirectorSQLExecutefor anUPDATE,DELETEorINSERTstatement, this field gives you the number of rows affected. Read about theSQLRowCountfunction, which returns the same information. You must call this function immediately after callingSQLExecDirectorSQLExecute.0007SQLGetDiagField( SQL_HANDLE_STMT,hstmt,NULL,SQL_DIAG_DYNAMIC_FUNCTION,charstring, sizeof(charstring),&charstring_size);
If the last call was
SQLExecDirectorSQLExecute, this field gives you a string that describes the type of SQL statement executed. Usually this is the first two or three <keyword>s in the statement. The official list of SQL statements and their function codes is shown at the end of this section.0012SQLGetDiagField( SQL_HANDLE_STMT,hstmt,NULL,SQL_DIAG_DYNAMIC_FUNCTION_CODE, &integer,NULL,NULL);
If the last call was
SQLExecDirectorSQLExecute, this field gives you the code value for the type of SQL statement executed; see the codes in the "DYNAMIC_FUNCTIONandDYNAMIC_FUNCTION_CODE" lists, above. If you allow users to type in SQL statements, it's handy to callSQLPrepareand then call this function, so you know what kind of SQL statement it is before you callSQLExecute.0013SQLGetDiagField(SQL_HANDLE_STMT,hstmt,NULL,SQL_DIAG_MORE,&integer,NULL,NULL);
The return value for this field is either 1 "true" or 0 "false": if there are more status records than would fit in the diagnostics area, you get a "true" code here. (Actually the Standard says that the returned value is 'Y' or 'N' but that must be an error.) You may or may not be able to change the maximum size of the diagnostics area with
SET TRANSACTION ... DIAGNOSTICS SIZEstatement.0034SQLGetDiagField( ...,...,NULL,SQL_DIAG_TRANSACTIONS_COMMITTED,&integer,NULL,NULL);
This field gives you the number of transactions committed.
0035SQLGetDiagField( ...,...,NULL,SQL_DIAG_TRANSACTIONS_ROLLED_BACK,&integer,NULL,NULL);
This field gives you the number of transactions rolled back.
0036SQLGetDiagField(...,...,NULL,SQL_DIAG_TRANSACTION_ACTIVE,&integer,NULL,NULL);
This field gives you a 1 "true" if a transaction is currently active. (A transaction is active if a Cursor is open or the DBMS is waiting for a deferred parameter.)
If the last call was SQLExecDirect or SQLExecute,
SQLGetDiagField's SQL_DIAG_DYNAMIC_FUNCTION gives you a string that
describes the type of SQL statement executed. As we said earlier, this is
usually the first two or three <keyword>s in the SQL statement. Here's the
official list of SQL statements and their function codes (note that not all
these SQL statements are executable in a CLI context; we have given a full list
here so as to avoid repetition elsewhere).
DYNAMIC_FUNCTION DYNAMIC_FUNCTION_CODE
(string) (number) (sqlcli.h definition)
ALLOCATE CURSOR 1 not defined
ALLOCATE DESCRIPTOR 2 not defined
CREATE TRANSLATION 79 not defined
DEALLOCATE DESCRIPTOR 15 not defined
DEALLOCATE PREPARE 16 not defined
DESCRIBE 20 not defined
DYNAMIC CLOSE 37 not defined
DYNAMIC DELETE CURSOR: 38 not defined
(positioned)
DYNAMIC FETCH 39 not defined
DYNAMIC OPEN 40 not defined
DYNAMIC UPDATE CURSOR: 42 not defined
(positioned)
EXECUTE 44 not defined
EXECUTE IMMEDIATE 43 not defined
FETCH 45 not defined
GET DESCRIPTOR 47 not defined
PREPARE 56 not defined
SELECT (multiple row) 21 not defined
SET CURRENT_PATH 69 not defined
SET DESCRIPTOR 70 not defined
DYNAMIC_FUNCTION DYNAMIC_FUNCTION_CODE
(string) (number) (sqlcli.h definition)
'' 0 <unknown statement type>
ALTER DOMAIN 3 SQL_DIAG_ALTER_DOMAIN
ALTER TABLE 4 SQL_DIAG_ALTER_TABLE
CLOSE CURSOR 9 SQL_DIAG_CLOSE_CURSOR
COMMIT WORK 11 SQL_DIAG_COMMIT
CONNECT 13 SQL_DIAG_CONNECT
CREATE ASSERTION 6 SQL_DIAG_CREATE_ASSERTION
CREATE CHARACTER SET 8 SQL_DIAG_CREATE_CHARACTER_SET
CREATE COLLATION 10 SQL_DIAG_CREATE_COLLATION
CREATE DOMAIN 23 SQL_DIAG_CREATE_DOMAIN
CREATE SCHEMA 64 SQL_DIAG_CREATE_SCHEMA
CREATE TABLE 77 SQL_DIAG_CREATE_TABLE
CREATE VIEW 84 SQL_DIAG_CREATE_VIEW
DECLARE CURSOR 101 SQL_DIAG_DECLARE_CURSOR
DELETE CURSOR 18 SQL_DIAG_DELETE_CURSOR
DELETE WHERE 19 SQL_DIAG_DELETE_WHERE
DISCONNECT 22 SQL_DIAG_DISCONNECT
DROP ASSERTION 24 SQL_DIAG_DROP_ASSERTION
DROP CHARACTER SET 25 SQL_DIAG_DROP_CHARACTER_SET
DROP COLLATION 26 SQL_DIAG_DROP_COLLATION
DROP DOMAIN 27 SQL_DIAG_DROP_DOMAIN
DROP SCHEMA 31 SQL_DIAG_DROP_SCHEMA
DROP TABLE 32 SQL_DIAG_DROP_TABLE
DROP TRANSLATION 33 SQL_DIAG_DROP_TRANSLATION
DROP VIEW 36 SQL_DIAG_DROP_VIEW
DYNAMIC DELETE CURSOR: 54 SQL_DIAG_DYNAMIC_DELETE_CURSOR
(preparable, positioned)
DYNAMIC UPDATE CURSOR 55 SQL_DIAG_DYNAMIC_UPDATE_CURSOR
(preparable, positioned)
GRANT 48 SQL_DIAG_GRANT
INSERT 50 SQL_DIAG_INSERT
OPEN 53 SQL_DIAG_OPEN
REVOKE 59 SQL_DIAG_REVOKE
ROLLBACK WORK 62 SQL_DIAG_ROLLBACK
SELECT (single row) 65 SQL_DIAG_SELECT
SELECT (dynamic single row) 41 SQL_DIAG_SELECT
SELECT CURSOR 85 SQL_DIAG_SELECT_CURSOR
(dynamic multiple row)
SET CATALOG 66 SQL_DIAG_SET_CATALOG
SET CONNECTION 67 SQL_DIAG_SET_CONNECTION
SET CONSTRAINT 68 SQL_DIAG_SET_CONSTRAINT
SET NAMES 72 SQL_DIAG_SET_NAMES
SET TIME ZONE 71 SQL_DIAG_SET_TIME_ZONE
SET SESSION AUTHORIZATION 76 SQL_DIAG_SET_SESSION_AUTHORIZATION
SET SCHEMA 74 SQL_DIAG_SET_SCHEMA
SET TRANSACTION 75 SQL_DIAG_SET_TRANSACTION
UPDATE CURSOR (positioned) 81 SQL_DIAG_UPDATE_CURSOR
UPDATE WHERE 82 SQL_DIAG_UPDATE_WHERE
DYNAMIC_FUNCTION DYNAMIC_FUNCTION_CODE
(string) (number) (sqlcli.h definition)
ALTER MODULE 95 not defined
ALTER ROUTINE 17 not defined
ALTER TYPE 60 not defined
ASSIGNMENT 5 not defined
BEGIN END 12 not defined
CASE 86 not defined
CREATE MODULE 51 not defined
CREATE ORDERING 114 not defined
CREATE TRANSFORM 117 not defined
DECLARE VARIABLE 96 not defined
DROP MODULE 28 not defined
FOR 46 not defined
FREE LOCATOR 98 not defined
HANDLER 87 not defined
HOLD LOCATOR 99 not defined
IF 88 not defined
LEAVE 89 not defined
LOOP 90 not defined
RESIGNAL 91 not defined
SET TRANSFORM GROUP 118 not defined
SIGNAL 92 not defined
TEMPORARY TABLE 93 not defined
WHILE 97 not defined
DYNAMIC_FUNCTION DYNAMIC_FUNCTION_CODE
(string) (number) (sqlcli.h definition)
CALL 7 SQL_DIAG_CALL
CREATE ROLE 61 SQL_DIAG_CREATE_ROLE
CREATE ROUTINE 14 SQL_DIAG_CREATE_ROUTINE
CREATE TRIGGER 80 SQL_DIAG_CREATE_TRIGGER
CREATE TYPE 83 SQL_DIAG_CREATE_TYPE
DROP ROLE 29 SQL_DIAG_DROP_ROLE
DROP ROUTINE 30 SQL_DIAG_DROP_ROUTINE
DROP TRANSFORM 116 SQL_DIAG_DROP_TRANSFORM
DROP TRIGGER 34 SQL_DIAG_DROP_TRIGGER
DROP ORDERING 115 SQL_DIAG_DROP_ORDERING
DROP TYPE 35 SQL_DIAG_DROP_TYPE
GRANT ROLE 49 SQL_DIAG_GRANT_ROLE
RELEASE SAVEPOINT 57 SQL_DIAG_RELEASE_SAVEPOINT
RETURN 58 SQL_DIAG_RETURN
REVOKE ROLE 60 SQL_DIAG_REVOKE_ROLE
SAVEPOINT 63 SQL_DIAG_SAVEPOINT
SET ROLE 73 SQL_DIAG_SET_ROLE
SET SESSION CHARACTERISTICS 109 SQL_DIAG_SET_SESSION_CHARACTERISTICS
START TRANSACTION 111 SQL_DIAG_START_TRANSACTION
(Note: In some contexts, the names DYNAMIC_FUNCTION and
DYNAMIC_FUNCTION_CODE are COMMAND_FUNCTION and
COMMAND_FUNCTION_CODE, respectively.)
The 28 "status records" in a diagnostics area can occur multiple times. You
must pass a record number between 1 and SQL_DIAG_NUMBER (or you can pass
any positive number and see whether SQLGetDiagField returns
SQL_NO_DATA). Other terms for Status Record are: "Descriptor Record"
(preferred by Microsoft) and Condition Information Item (preferred by the SQL
Standard in non-CLI contexts). Strings are returned according to the rules of
Character String Retrieval.
< 0- A status record with a number less than zero identifies an implementation-defined diagnostics field.
0004SQLGetDiagField( ...,...,n,SQL_DIAG_SQLSTATE,charstring,sizeof(charstring), &charstring_size);
This field gives you a 5-character status code -- remember to allow 6 characters because of the null terminator.
SQLSTATEis the most important diagnostics field. You'll find the complete list ofSQLSTATEvalues, often called simply status codes, at the end of this chapter. Quite often, theSQLSTATEclass determines whether the other diagnostics fields have meaningful values.0005SQLGetDiagField(...,...,n,SQL_DIAG_NATIVE,&integer,NULL,NULL);
This field gives you an integer which has an implementation-defined numeric code for the error type. If your DBMS has been around for a few years, this will be the same as the
SQLCODEvalue. It was once standard for DBMSs to returnSQLCODE, and sometimes (for instance with IBM's DB2) theSQLCODEis more informative than theSQLSTATEvalue. But there is no standardized interpretation for the codes, except that values less than zero are "errors", equal to zero is "success", greater than zero are "warnings", and specifically +100 is "warning-no data".0006SQLGetDiagField( ...,...,n,SQL_DIAG_MESSAGE_TEXT,charstring,sizeof(charstring), &charstring_size);
This field gives you an error message -- sometimes merely an explanation of the
SQLSTATEmeaning, but the better DBMSs have context-sensitive tips. Useful for displays. Often, due to an ODBC requirement, messages start with bracketed information about the server and driver.0008SQLGetDiagField( ...,...,n,SQL_DIAG_CLASS_ORIGIN,charstring,sizeof(charstring), &charstring_size);
This field gives you the naming authority responsible for the definition of the class (the first two letters of
SQLSTATE). Example: 'ISO 9075' would mean that the condition is documented in ISO/IEC 9075:1992 and is therefore "standard".0009SQLGetDiagField( ...,...,n,SQL_DIAG_SUBCLASS_ORIGIN,charstring,sizeof(charstring), &charstring_size);
This field gives you the naming authority responsible for the definition of the subclass (the last three letters of
SQLSTATE). Example: 'ODBC 3.0' would mean that the condition is documented in Microsoft's ODBC manual version 3.0 but is not in any ISO specification, and is therefore "not standard".0010SQLGetDiagField( ...,...,n,SQL_DIAG_CONNECTION_NAME,charstring,sizeof(charstring), &charstring_size);
This field gives you the <Connection name>. With the CLI this field is of minor importance, because the primary identifier for an SQL-Connection is the
hdbc.0011SQLGetDiagField( ...,...,n,SQL_DIAG_SERVER_NAME,charstring,sizeof(charstring), &charstring_size);
If the last SQL statement was a failed
CONNECT,DISCONNECTorSET CONNECTION, this field gives you the server that the attempt failed with. Otherwise, you get the same information that you'd get by callingSQLGetInfo(...,SQL_DATA_SOURCE_NAME,...).0014SQLGetDiagField(...,...,n,SQL_DIAG_CONDITION_NUMBER,&integer,NULL,NULL);
This field gives you the number of the Status Record (the terms "condition number" and "status record number" are synonymous). This will be the same thing as the
RecordNumberparameter, so you won't find out anything new here.0015SQLGetDiagField( ...,...,n,SQL_DIAG_CONSTRAINT_CATALOG,charstring,sizeof(charstring), &charstring_size);
0016SQLGetDiagField( ...,...,n,SQL_DIAG_CONSTRAINT_SCHEMA,charstring,sizeof(charstring), &charstring_size);
0017SQLGetDiagField( ...,...,n,SQL_DIAG_CONSTRAINT_NAME,charstring,sizeof(charstring), &charstring_size);
If
SQLSTATEis'23000'(integrity constraint violation) or'27000'(triggered data change violation) or'40002'(transaction rollback-integrity constraint violation), then fields0015,0016and0017give you the Catalog, Schema and name of the violated Constraint.0018SQLGetDiagField( ...,...,n,SQL_DIAG_CATALOG_NAME,charstring,sizeof(charstring), &charstring_size);
0019SQLGetDiagField( ...,...,n,SQL_DIAG_SCHEMA_NAME,charstring,sizeof(charstring), &charstring_size);
0020SQLGetDiagField( ...,...,n,SQL_DIAG_TABLE_NAME,charstring,sizeof(charstring), &charstring_size);
0021SQLGetDiagField( ...,...,n,SQL_DIAG_COLUMN_NAME,charstring,sizeof(charstring), &charstring_size);
Fields
0018,0019,0020and0021give you the Catalog, Schema and Table identifiers, plus the Column identifier if applicable, for what "caused" the problem. IfSQLSTATE = '23000'or'27000'or'40002', these fields will identify the Table that the violated Constraint is associated with (assuming there is one such Table). IfSQLSTATE = '42000', this is the Object that couldn't be found or that you lack Privileges on (the Standard contains some ambiguities here, but it seems that these fields may be blank for access violations). IfSQLSTATE = '44000', this is the View that has a violatedWITH CHECK OPTION. IfSQLSTATE = '09000'or'40004', this is the Table with the Trigger that can't be executed. IfSQLSTATEis any other value, results are implementation-dependent.0022SQLGetDiagField( ...,...,n,SQL_DIAG_CURSOR_NAME,charstring,sizeof(charstring), &charstring_size);
If
SQLSTATE = '01001'or'24000', this field gives you the identifier of a Cursor. IfSQLSTATEis anything else, results are implementation-dependent.0023SQLGetDiagField(...,...,n,SQL_DIAG_MESSAGE_LENGTH,&integer,NULL,NULL);
This field gives you the character length of the implementation-defined message string. You can get the same information using
SQL_DIAG_MESSAGE_TEXT. By the way, the C include filesqlcli.hsays "#define SQL_MAXIMUM_MESSAGE_LENGTH 512" so the suggestion is that you allow 512 bytes for the message -- but it's only a suggestion. It might be interesting to compareSQL_MAXIMUM_MESSAGE_LENGTHwith whatSQLGetDiagFieldreturns forSQL_DIAG_MESSAGE_LENGTH.0024SQLGetDiagField(...,...,n,SQL_DIAG_MESSAGE_OCTET_LENGTH,&integer,NULL,NULL);
This field gives you the octet length of the implementation-defined message string. This will be the same as the message length in characters if the Character set is 8-bit.
0025SQLGetDiagField( ...,...,n,SQL_DIAG_CONDITION_NAME,&charstring,sizeof(charstring), &charstring_size);
This field gives you the name of an unhandled user-defined exception.
0026SQLGetDiagField( ...,...,n,SQL_DIAG_PARAMETER_NAME,charstring,sizeof(charstring), &charstring_size);
This field gives you the name of a parameter -- presumably the parameter which contained bad (input) data. Since named parameters are not a universal feature, most DBMSs will not return anything here.
0027SQLGetDiagField( ...,...,n,SQL_DIAG_ROUTINE_CATALOG,charstring,sizeof(charstring), &charstring_size);
0028SQLGetDiagField( ...,...,n,SQL_DIAG_ROUTINE_SCHEMA,charstring,sizeof(charstring), &charstring_size);
0029SQLGetDiagField( ...,...,n,SQL_DIAG_ROUTINE_NAME,charstring,sizeof(charstring), &charstring_size);
0030SQLGetDiagField( ...,...,n,SQL_DIAG_SPECIFIC_NAME,charstring,sizeof(charstring), &charstring_size);
If the
SQLSTATEerror class is '38' (external routine exception) or '39' (external routine invocation exception), fields0027,0028and0029give you the full identifier of the routine that "caused" the error, while field0030gives you the routine's specific name.0031SQLGetDiagField( ...,...,n,SQL_DIAG_TRIGGER_CATALOG,charstring,sizeof(charstring), &charstring_size);
0032SQLGetDiagField( ...,...,n,SQL_DIAG_TRIGGER_SCHEMA,charstring,sizeof(charstring), &charstring_size);
0033SQLGetDiagField( ...,...,n,SQL_DIAG_TRIGGER_NAME,charstring,sizeof(charstring), &charstring_size);
If
SQLSTATE='40004'or'09000', fields0031,0032and0033give you the full identifier of the Trigger that "caused" the problem.
Algorithm:
If (HandleType <> SQL_HANDLE_STMT, SQL_HANDLE_ENV, SQL_HANDLE_DBC, or
SQL_HANDLE)DESC)
return error: CLI-specific condition-invalid handle
If (handle isn't really the type indicated by HandleType)
return error: CLI-specific condition-invalid handle
If (DiagIdentifier isn't a valid code)
return error: HY024 CLI-specific condition-invalid attribute value
If (FieldIdentifier is for one of the Status Record fields)
If (RecordNumber < 1)
return error: 35000 invalid condition number -
If (RecordNumber > actual number of status records)
return warning: 01000 no data -
If (FieldIdentifier is for one of the Header fields)
If (FieldIdentifier == SQL_DIAG_ROW_COUNT)
If (last call was not SQLExecute or SQLExecDirect)
return error: HY092 CLI-specific condition-invalid attribute identifier
Otherwise: return a diagnostics-area field, as already described.
Notes:
Status Records are sorted according to the severity of the error class:
- Highest: Errors that cause rollback (class '40').
- Lower: Ordinary errors (everything except '40' or '01' or '02').
- Lower: No-data warning (class '02').
- Lowest: Mere warning (class '01').
The first Status Record is thus the most important. If the return code is
SQL_ERRORyou can be sure that the first Status Record describes an error condition.The
SQLSTATEs associated with the possibleSQLGetDiagFielderrors are only mentioned for documentary reasons. TheSQLGetDiagFieldfunction does not itself post any diagnostics. The way you check for errors is: look at the return code, then start guessing. These tips may be useful:If (SQLGetDiagField returns SQL_SUCCESS_WITH_INFO) Probably the DiagInfo buffer is too small. Compare BufferLength (the maximum size of the DiagInfo buffer) to StringLength (the actual size of the string to be returned). If BufferLength is smaller, there's your problem. If (SQLGetDiagField returns SQL_INVALID_HANDLE) Sure, check that the handle is valid. But this problem can also occur if SQLHandleType is not SQL_HANDLE_..., so check that too. If (SQLGetDiagField returns SQL_ERROR) Check HandleType+DiagIdentifier. If the handle isn't a hstmt, then you can't ask for SQL_ROW_COUNT. Check RecordNumber. If you're looking for a header field, then it doesn't matter what you pass in RecordNumber. If you're looking for a status field, then RecordNumber must be >= 1. Check DiagIdentifier. If you use constants defined in sqlcli.h: the value here should be a constant beginning with SQL_DIAG_... -- but that's not enough. Also, make sure it's one of the values listed above. Check BufferLength. If you're looking for a numeric field, then it doesn't matter what you pass in BufferLength. If you're looking for a string field, then BufferLength must be >= 1. If (SQLGetDiagField returns SQL_NO_DATA) This always means that the value you passed in RecordNumber is greater than the value in the diagnostics area's NUMBER field. For example: you passed 1 but there are zero status records.
Some header fields always have valid information, even if the last call didn't end with an error or warning. For example, you can find out what the last executed SQL statement was, and how many rows it affected, even if the number of Status Records is zero.
The great majority of diagnostics are only applicable to stmts. You will
only need to get a dbc's diagnostics area fields if the last call used a
dbc handle, which usually means if the last call was connect,
disconnect, endtran or some variants of allochandle and
freehandle. As for envs and descs, they too have diagnostics
areas, but use of SQLGetDiagField with henvs and hdescs is
esoteric.
Example:
#include "sqlcli.h"
...
SQLHSTMT hstmt;
SQLINTEGER diag_number; /* gets # of status records */
SQLINTEGER row_number;
SQLCHAR sqlstate[5+1]; /* gets SQLSTATE */
SQLCHAR catalog[128+1]; /* gets a catalog name */
SQLSMALLINT catalog_octet_length;/* size of catalog name */
SQLCHAR schema[128+1]; /* gets a schema name */
SQLSMALLINT schema_octet_length; /* size of schema name */
SQLCHAR name[128+1]; /* gets an object name */
SQLSMALLINT name_octet_length; /* size of name */
...
/* Make a one-Column Table, with a CHECK Constraint. */
SQLExecDirect(hstmt,"CREATE TABLE Ts(col_1 INT,CHECK (col_1=7);",SQL_NTS);
/* Try to violate the CHECK Constraint. */
SQLExecDirect(hstmt,"INSERT INTO Ts VALUES(15);",SQL_NTS);
/* Find out how many status records are in the diagnostics area. */
SQLGetDiagField(SQL_HANDLE_STMT,NULL,SQL_DIAG_COUNT,&diag_count,NULL,NULL);
/* Loop: For each status record ... */
for (row_number=1; row_number<=diag_number; ++row_number) {
/* Get SQLSTATE. */
SQLGetDiagField(
SQL_HANDLE_HSTMT,hstmt,row_number,SQL_DIAG_SQLSTATE,sizeof(sqlstate),
sqlstate,NULL);
/* The first two octets of SQLSTATE are the error class. */
/* if class = '23' integrity constraint violation: what constraint? */
if (memcmp(sqlstate,"23",2)==0) {
/* Get Catalog . Schema . name of the Constraint */
SQLGetDiagField(
SQL_HANDLE_STMT,hstmt,row_number,SQL_DIAG_CONSTRAINT_CATALOG,catalog,
sizeof(catalog),&catalog_size);
SQLGetDiagField(
SQL_HANDLE_STMT,hstmt,row_number,SQL_DIAG_CONSTRAINT_SCHEMA,
schema,sizeof(schema),&schema_size);
SQLGetDiagField(
SQL_HANDLE_STMT,hstmt,row_number,SQL_DIAG_CONSTRAINT_NAME,
name,sizeof(name),&name_size);
} }
ODBC: The SQLGetDiagField function is new in ODBC 3.0 (older ODBC
versions had only SQLError for getting diagnostics fields). In addition to
all the standard options, ODBC has an additional useful-looking one:
SQL_DIAG_CURSOR_ROW_COUNT, for getting the number of rows in an open
Cursor. (ODBC also gives row and Column number within the result set.) ODBC,
unlike standard SQL, sorts status records by row number.
Function Prototype:
SQLRETURN SQLGetDiagRec(
SQLSMALLINT HandleType, /* 16-bit input */
SQLINTEGER Handle, /* 32-bit input */
SQLSMALLINT RecordNumber, /* 16-bit input */
SQLCHAR *Sqlstate, /* CHAR* output */
SQLINTEGER *NativeError, /* 32-bit output */
SQLCHAR *MessageText, /* CHAR* output */
SQLSMALLINT BufferLength, /* 16-bit input */
SQLSMALLINT *TextLength); /* 16-bit output */
Job: Get SQLSTATE, sqlcode and error-message from one status
record.
Algorithm:
If (HandleType <> SQL_HANDLE_ENV | SQL_HANDLE_DBC | SQL_HANDLE_STMT
| SQL_HANDLE_DESC)
Or (what handle references isn't the type that HandleType indicates)
return error: CLI-specific condition-invalid handle
If (RecordNumber < 1)
return error: 35000 invalid condition number -
If (RecordNumber > number of status records in diagnostics area)
/* SQLGetDiagRec returns +100, but doesn't make its own diagnostics */
/* In ODBC, some output parameters would be changed anyway. */
return error: no data -
If (SqlState is not a null pointer)
Set *SQLState = status record [RecordNumber] . SQL_DIAG_SQLSTATE
If (NativeError is not a null pointer)
Set *NativeError = status record [RecordNumber] . SQL_DIAG_NATIVE_ERROR
If (MessageText is not a null pointer)
/* ... The message text is copied in the usual Character String
Retrieval way. */
Set *MessageText = status record [RecordNumber ]. SQL_DIAG_MESSAGE_TEXT
For description of the SQL_DIAG_SQLSTATE, SQL_DIAG_NATIVE_ERROR, and
SQL_DIAG_MESSAGE_TEXT fields, see the SQLGetDiagField descriptions.
Notes:
The assumption behind
SQLGetDiagRecis that, when you want diagnostics information, you specifically wantSQL_DIAG_SQLSTATE,SQL_NATIVE_ERRORandSQL_DIAG_MESSAGE_TEXT(both contents and length). If the assumption is wrong and you want only some of these fields, or you want other fields, then you might find thatSQLGetDiagFieldis all you need. We observed similar assumptions at work when we looked at thedescfunctions,SQLGetDescFieldandSQLGetDescRec.Calls to
SQLGetDiagRecare frequent after a CLI function returns an error. That is:if (SQLfunction(...) < 0) SQLGetDiagRec(...);
is the normal way of calling.
Example: This example shows that SQLGetDiagRec and SQLGetDiagField
may be similar. The first call retrieves dbc's SQLSTATE using
SQLGetDiagField -- we pass NULL for the final 4 parameters because we
don't care about them.
#include "sqlcli.h"
SQLCHAR sqlstate[6];
...
SQLGetDiagField(SQL_HANDLE_DBC,hdbc,1,sqlstate,sizeof(sqlstate),NULL);
SQLGetDiagRec(SQL_HANDLE_DBC,hdbc,1,sqlstate,NULL,NULL,NULL,NULL);
This example shows the minimalist error-handling procedure for applications
that are written in a hurry: if anything goes wrong, print a message and stop
the program. The symbol SQL... means "any CLI function". The "if
(sqlreturn < 0)" test uses an assumption (true at the moment) that
SQL_SUCCESS and SQL_SUCCESS_WITH_INFO and SQL_NO_DATA -- the
non-problems -- are all greater than or equal to zero; SQL_INVALID_HANDLE
and SQL_NEED_DATA and SQL_ERROR -- the problems -- are less than zero.
#include "sqlcli.h"
SQLCHAR sqlstate[5+1];
SQLCHAR sqlmessage[SQL_MAX_MESSAGE_LENGTH+1];
SQLRETURN sqlreturn;
...
sqlreturn = SQLFunc(...);
if (sqlreturn < 0) {
printf("Error: \n");
if (sqlreturn==SQL_INVALID_HANDLE) {
/* For the SQL_INVALID_HANDLE return code, there are no associated
status records. So we have to make up and display our own error. */
printf("Invalid handle.\n"); }
if (sqlreturn==SQL_NEED_DATA) {
/* This is shown for completeness; "need data" needs discussion later */
printf("Need data.\n"); }
if (sqlreturn==SQL_ERROR) {
if (SQLGetDiagRec(...,...,1,sqlstate,NULL,sqlmessage,NULL,NULL)
== SQL_NO_DATA) {
/* Read the SQLAllocEnv description for special notes about handling
errors from that function. For all other CLI functions, there
will be at least one status record, so you won't get here. */
printf("(No status rows).\n"); }
else {
printf("SQLSTATE=%s.\n",sqlstate);
printf("MESSAGE_TEXT=%s.\n",sqlmessage);
exit(1); }
This example displays warning or error messages after an execution.
#include "sqlcli.h"
SQLCHAR sqlstate[6], sqlmessage[SQL_MAX_MESSAGE_LENGTH+1];
SQLINTEGER sqlnative, sqlmore;
SQLSMALLINT sqlrecordnumber, sqlmessagelength;
SQLHSTMT hstmt;
SQLRETURN sqlreturn1, sqlreturn2;
...
sqlreturn1 = SQLExecDirect(hstmt,"SQL statement goes here",SQL_NTS);
if (sqlreturn1 == SQL_ERROR || sqlreturn1 == SQL_SUCCESS_WITH_INFO) {
for (sqlrecordnumber=1;;++sqlrecordnumber) {
sqlreturn2=SQLGetDiagRec(
SQL_HANDLE_STMT,hstmt,sqlrecordnumber,sqlstate,&sqlnative,
sql_message,sizeof(sql_message),&sql_message_length);
if (sqlreturn2 == SQL_NO_DATA || sqlreturn2 < 0) break;
printf("SQLExecDirect returned: %d\n",sqlreturn1);
printf("Status code = %s\n",sqlstate);
printf("Native code or sqlcode = %ld\n",sqlnative);
printf("Error/Warning message = %s.\n",sqlmessage);
if (sqlmessagelength>sizeof(sqlmessage) printf("May be truncated."); }
SQLGetDiagField(SQL_HANDLE_STMT,hstmt,1,SQL_DIAG_MORE,&sqlmore,NULL,NULL);
if (sqlmore) {
printf("Not all Error/Warning conditions have been displayed!\n"); }
ODBC: The SQLGetDiagRec function is new in ODBC 3.0; applications for
earlier ODBC versions use SQLError, which is similar. ODBC example programs
often use the names SqlState, Msg and rc where we have tended to
use SQLSTATE, sqlmessage and sqlreturn.
Function Prototype:
SQLRETURN SQLError(
SQLHENV henv, /* 32-bit input */
SQLHDBC hdbc, /* 32-bit input */
SQLHSTMT hstmt, /* 32-bit input */
SQLCHAR *Sqlstate, /* pointer to char* output -- char[5+1] */
SQLINTEGER *NativeError, /* pointer to 32-bit output */
SQLCHAR *MessageText, /* pointer to char* output */
SQLSMALLINT BufferLength, /* 16-bit input */
SQLSMALLINT *TextLength /* pointer to 16-bit output */
);
Job: Return "diagnostics" -- that is, the completion conditions (warnings)
and exception conditions (errors) that are associated with the env or
dbc or stmt.
Although all standard DBMSs will support it, and although it is an official
SQL3 function, SQLError is obsolete. The modern way to get diagnostics is
with SQLGetDiagRec or SQLGetDiagField.
Algorithm:
/* The diagnostics come from a stmt or (if hstmt
is 0) from a dbc or (if hdbc is also 0) from an env.
SQLError does not get diagnostics from
all three resources at once, or from a desc. */
If (hstmt <> 0)
Set Handle = hstmt
Else
/* hstmt == 0 */
If (hdbc <> 0)
Set Handle = hdbc
Else
/* hstmt == 0 and hdbc == 0 */
If (henv <> 0)
Set Handle = henv
Else
/* hstmt == 0 and hdbc == 0 and == 0 */
return error: CLI-specific condition-invalid handle
/* Now Handle == handle of stmt or dbc or env */
/* The diagnostics, if any, were created by the last CLI function
that was called using Handle. */
For (each status record generated by the last CLI function)
If (we have already called SQLError and gotten this status record)
continue
If (there are no more status records)
return SQL_NO_DATA (+100)
/* ... a DBMS that follows the ODBC requirements would set
sqlstate = '00000', NativeError = +100, before returning
SQL_NO_DATA. This is a signal to the application program that it
should break out of a loop. */
Else
break
/* We are now looking at a status record which was generated by a
previous function call using the (passed) Handle. The following
is the same as if we called:
SQLGetDiagRec (<handle type>, <Handle>, <# of status record>,
Sqlstate,NativeError, MessageText, BufferLength, TextLength) */
Return status record's SQL_DIAG_SQLSTATE value to Sqlstate.
Return status record's SQL_DIAG_MESSAGE_TEXT value to MessageText
(the return happens in the usual way for Character String Retrieval).
Return status record's SQL_DIAG_NATIVE value, presumably SQLCODE, to
NativeError.
Notes: The last five parameters of SQLError are the same as the last
five parameters of SQLGetDiagRec. The effective difference is that, with
SQLGetDiagRec, you pass a RecordNumber parameter, while with
SQLError you depend on the DBMS to keep an internal counter -- SQLError
will always retrieve the next status record.
Example:
#include "sqlcli.h"
...
SQLCHAR sqlstate[6]; /* not 5: 6!! Allow for \0 at the end! */
SQLINTEGER sqlnative; /* this is a "long int" */
SQLHSTMT hstmt;
...
sqlreturn=SQLExecDirect(hstmt,"INSERT VALUES;",SQL_NTS);
/* The above is illegal SQL so the return code will be negative */
if (sqlreturn==SQL_ERROR) goto error_handler_for_stmt;
...
error_handler_for_stmt:
/* **TRAP: sometimes errors happen for dbc or env functions too, each
type of handle needs a separate error-handling procedure. */
SQLError(0,0,hstmt,sqlstate,&sqlnative,NULL,NULL,NULL);
/* sqlstate is probably '42000' */
/* sqlnative is probably less than zero */
...
ODBC: The SQLError function has been around since ODBC 1.0. In ODBC
3.0, it is labelled "deprecated" and ODBC's driver manager will map it to
SQLGetDiagRec.
Function Prototype:
SQLRETURN SQLRowCount(
SQLHSTMT hstmt, /* 32-bit input -- statement handle */
SQLINTEGER *RowCount /* 32-bit output */
);
Job: Find out how many rows were inserted or updated or deleted during the
execution of the last SQLExecute or SQLExecDirect call.
Algorithm:
If (hstmt does not refer to an executed statement)
return error: HY010 CLI-specific condition-function sequence error
Set *RowCount = stmt's diagnostics area's SQL_DIAG_ROW_COUNT value.
Notes:
The row count is the number of rows affected when you call
SQLExecuteorSQLExecDirect, and the SQL statement you're executing begins withINSERTorUPDATEorDELETE(the SQL-data change statements).Only directly affected rows matter. If you delete one primary key row, and there are 10 foreign key rows that are also deleted because the
FOREIGN KEYConstraint definition includesON DELETE CASCADE, then a total of 11 rows are deleted: 1 directly, 10 indirectly -- so theSQLRowCountfunction returns 1.Only "searched
UPDATE" and "searchedDELETE" statements matter. TheUPDATE ... WHERE CURRENT OF<Cursor> andDELETE ... WHERE CURRENT OF<Cursor> statements have no effect on row count.With some DBMSs,
SQLRowCountwill contain the number of rows returned by the lastSELECTstatement. That's very useful if you want to display the results on the screen along with a Windows scrollbar. If your DBMS won't give you that, there are other options: (a) use aSELECT COUNT(*)statement (may be unreliable in a multi-user environment, may fail if selection is of a grouped View), (b) callSQLGetDiagFieldwith theSQL_DIAG_CURSOR_ROW_COUNToption (non-standard, works only with ODBC) or (c) callSQLFetchScrolluntil the return isSQL_NO_DATA.You can get the same result by calling:
SQLGetDiagField(SQL_HANDLE_STMT,hstmt,SQL_DIAG_ROW_COUNT,&RowCount,NULL,NULL);
but
SQLGetDiagFieldonly returns results for "the last function", which means (for instance) that if you've fetched since you executed theUPDATEstatement,SQLGetDiagFieldcan't tell you anything.SQLRowCount, which returns results for "the lastSQLExecuteorSQLExecDirectfunction", is better.If the number of changed rows is zero, then
SQLExecuteandSQLExecDirectboth returnSQL_NO_DATA(notSQL_SUCCESSorSQL_SUCCESS_WITH_INFO).
Example:
#include "sqlcli.h"
SQLINTEGER row_count;
...
if (SQLExecDirect(hstmt,"INSERT INTO Table_1 VALUES (1);",SQL_NTS)>=0) {
if (SQLRowCount(hstmt,&row_count)>=0) {
/* The value of row_count is 1. */ } }
ODBC: The SQLRowCount function has been around since ODBC 1.0.
And that's it for the diagnostic functions. Now let's take a look at the
Standard's SQLSTATE codes.
The SQL status parameter SQLSTATE is a 5-character string value, with 2
parts: the first 2 characters represent a class value, the following 3
characters represent a subclass value. SQLSTATE codes are limited to digits
and simple Latin upper-case letters.
Class values that begin with 0, 1, 2, 3, 4, A, B, C, D, E, F, G or H are called standard-defined classes and identify status conditions defined in either the SQL Standard or some other international standard. Subclass values associated with standard-defined classes that also begin with one of those 13 characters are called standard-defined subclasses and also identify status conditions defined in either the SQL Standard or some other international standard, while subclass values associated with standard-defined classes that begin with 5, 6, 7, 8, 9, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y or Z are called implementation-defined subclasses and identify status conditions defined by DBMS vendors.
Class values that begin with 5, 6, 7, 8, 9, I, J, K, L, M, N, O, P, Q, R, S, T,
U, V, W, X, Y or Z are called implementation-defined classes and identify
exception conditions defined by DBMS vendors. All subclass values except '000'
(no subclass) associated with implementation-defined classes are
implementation-defined subclasses. An implementation-defined completion
condition is identified by returning an implementation-defined subclass
together with one of the SUCCESSFUL COMPLETION, WARNING or NO DATA
classes.
If a subclass value is not specified for a condition, then either subclass '000' or an implementation-defined subclass is returned.
If multiple conditions are returned, then your DBMS decides which condition is
the one that will be returned in the SQLSTATE parameter. (Any number of
condition values, in addition to SQLSTATE, may be returned in the
diagnostics area.)
Using the CLI, you can retrieve SQLSTATE with one of the diagnostics
functions (SQLGetDiagField, SQLGetDiagRec or SQLError). Using
embedded SQL, you can retrieve SQLSTATE with GET DIAGNOSTICS, or you
can let the DBMS fill it in automatically. Since the status codes are
reasonably standard, application programmers can anticipate what SQLSTATE
values may crop up, and they can write appropriate error-testing or descriptive
routines. The rest of this chapter contains detailed descriptions for all
SQLSTATEs which are defined in the SQL Standard, as well as summary
information about some SQLSTATEs which are used in common application
environments, such as ODBC.
We suggest you examine the list of SQLSTATE codes and decide which warnings
and errors you must take specific action for. Make a case statement which will
be executed after each SQL operation. If you are programming for ODBC 3.x,
don't worry about the obsolete ODBC 2.0 entries in the list -- Microsoft's
driver manager will translate them to the current standardized value. If you
use the list in conjunction with some vendor manual, you will probably notice
that our descriptions are more specific and detailed; however, you should
prefer the vendor's description in case of outright contradiction. For casual
users, the DBMS's in-context error-message displays, accompanied by a pointer
to the offending SQL statement, will suffice. But that is an "after-the-fact"
proposition. If your job is to program for errors that haven't happened yet,
you need a complete list with some examples and explanations for every entry.
Here is an example of a tiny C program (runnable in a DOS box) with one embedded SQL statement, followed by a case statement that checks for an error:
EXEC SQL INCLUDE SQLCA; /* so error message defined here? */
EXEC SQL BEGIN DECLARE SECTION;
char sqlcode[6]; /* Notice we allow 6 characters, there's a \0 too */
EXEC SQL END DECLARE SECTION;
void main ()
{
EXEC SQL DROP TABLE x RESTRICT;
portability(sqlstate); /* Perhaps change the class */
switch (sqlstate) {
case '.....': /* Okay */
case '.....': /* Table not found */
case '.....': /* Another table depends */
default: /* All other errors */
} }
/* In a portable program you won't know what subclasses were added by each
vendor, so change all implementation-defined subclasses to '000'. NIST uses
a similar technique for its compliance-test programs. */
void portability (char sqlstate[])
{
if (sqlstate[2]>='I' || (sqlstate[2]>='4' && sqlstate[0]<='9') {
/* The third character of sqlstate, which is the first byte of subclass,
is a letter >= 'I' or is a digit >= '4' -- implementation-defined. */
sqlstate[2]=sqlstate[3]=sqlstate[4]='0'; } }/* subclass = '000' */
The following SQLSTATE codes identify a successful completion condition.
00000 successful completion- The "successful completion" class identifies "completion conditions" (as
opposed to "exception conditions", which are errors). In the case of
SQLSTATE 00000, the last SQL operation sailed through without a problem. The00000status code is invisible to CLI programs because the Standard says: if the return code= SQL_SUCCESS, then no status records are generated.
The following SQLSTATE codes identify a successful completion condition
with a warning.
01000 warning- The "warning" class identifies completion conditions that were processed
with some type of warning. They are usually associated with some
DBMS-specific informational message, which you can retrieve with
SQLGetDiagRecorGET DIAGNOSTICS. In the CLI, the existence of a warning diagnostic is signalled by theSQLRETURNvalueSQL_SUCCESS_WITH_INFO (1).SQLSTATE 01000is the miscellaneous-warning category. For completion conditions that fit in the warning class, but don't fit in one of the subclasses listed below (such as01001), this is what you'll get. Suggestion for thisSQLSTATE: get the message withSQLGetDiagRec, display the message and continue. 01001 warning-cursor operation conflict- This
SQLSTATEwas included in the SQL-92 Standard by mistake; the corrigendum bulletin #3 says it should only be an SQL3SQLSTATE. The NIST tests expect DBMSs to returnSQLSTATE=01001if youDELETEwith and without a Cursor in the same transaction. 01002 warning-disconnect error- There was an error during execution of the CLI function
SQLDisconnect, but you won't be able to see the details because theSQLDisconnectsucceeded. 01003 warning-null value eliminated in set function- The set function had to ignore a
NULLwhen working on its argument. For example, theSUMof 5 andNULLis 5 (notNULL), but01003warns you that the result may be inaccurate becauseNULLusually means "unknown". 01004 warning-string data, right truncation- Happens when you try to squeeze a 5-character (or bit) value into a
4-character (or bit) space (remember that "string" can be either
character or bit string). The truncation should happen for data outbound
from the database to a host variable, for example in the statement
"SELECT ... INTO :x". It should not happen for data inbound to the database -- that would be not a warning but an error (22001). 01005 warning-insufficient data item descriptor areas- Every descriptor area has multiple IDAs. You need one IDA per Column of a result set, or one per parameter. Either reduce the number of Columns in the select list or reduce the number of ?s in the SQL statement as a whole.
01006 warning-privilege not revoked- There is no Privilege descriptor for a combination of: this grantor,
this grantee, this action. The DBMS does not return an error if a
Privilege revocation fails -- instead, it revokes whatever Privileges it
can and returns this warning. If an equivalent Privilege was granted by
a different grantor, it continues to exist, but warning
01006does not appear. 01007 warning-privilege not granted- Probably the grantor doesn't hold a Privilege
WITH GRANT OPTION. For example: Susan has theUPDATEPrivilege onTABLE_1(without grant option) and theINSERTPrivilege onTABLE_1(WITH GRANT OPTION). She says:"GRANT SELECT, INSERT, UPDATE ON Table_1 TO Joe;". Result: Joe gets theINSERTPrivilege, but not theSELECTorUPDATEPrivileges, hence this warning (some DBMSs will generate the warning twice because two Privileges are ungranted). Warning01007also appears if the grantor has zero PrivilegesWITH GRANT OPTION, and says"GRANT ALL PRIVILEGES ...". On the other hand, if the grantor holds zero Privileges period, the result is error42000instead of warning01007. 01008 warning-implicit zero-bit padding- Suppose you insert
B'1'-- a one-bit binary <literal> -- into a two-bit Column. The second bit will be a 0, and the DBMS will return this warning. 01009 warning-search condition too long for information schema- Suppose you say "
CREATE TABLE ... CHECK(<condition>)", and the length of <condition> is larger than what can be stored in theINFORMATION_SCHEMAView,CHECK_CONSTRAINTS, in itsCHECK_CLAUSEColumn. The Table will still be created -- this warning only means you won't be able to see the entire information about the Table when you look atINFORMATION_SCHEMA. See also:0100Aand0100B. 0100A warning-query expression too long for information schema- This is the same as warning
01009except that instead of a search condition (as in aCHECKclause), you're using a query condition (usuallySELECT). Thus, if you say"CREATE VIEW ..."with a very long query, the size of ColumnVIEW_DEFINITIONin ViewVIEWSinINFORMATION_SCHEMAis a limiting factor. 0100B warning-default value too long for information schema- This is the same as warning
01009except that instead of a search condition (as in aCHECKclause), you're using a default value.
0100C warning-dynamic result sets returned
0100D warning-additional result sets returned
0100E warning-attempt to return too many result sets
0100F warning-fewer locators than dynamic result sets
0102F warning-array data, right truncation
01Hxx warning-external routine warning- The author of the external routine chooses the subclass value of
xx. 01S00 warning-invalid connection string attribute(ODBC 2+3)- The ODBC function
SQLBrowseConnectorSQLDriverConnectrequires a parameter string with a certain format. Connection happens anyway. 01S01 warning-error in row(ODBC 3)- With ODBC 3.x, this warning happens only for
SQLExtendedFetchor forSQLFetchScroll. Although an "error" has happened, this is only a warning because other rows might have been returned without error. 01S02 warning-option value changed(ODBC 3)- You used an ODBC function to change an option (e.g.:
SQLSetEnvAttr). This warns you that the change occurred. 01S06 warning-attempt to fetch before the result set returned the first rowset(ODBC 3)- It would be clearer to use this wording: "attempt to fetch before the
first row in the result set". This error would be returned if your last
fetch was of the first row in the result set and now you attempt to
fetch
PRIOR. 01S07 warning-fractional truncation(ODBC 3)- You'll get this error if, for example, you assigned the value 5.432 to a
Column whose definition is
DECIMAL(3,2)-- that is, the scale of the target is 2 and the scale of the source is 3, so only 5.4 is stored. A problem with the non-fractional part would result in another SQLSTATE:22003. 01S08 warning-error saving file DSN(ODBC 3)- A warning from
SQLDriverConnect. The Connection succeeds, but the file indicated by the FILEDSN keyword was not saved. 01S09 warning-invalid keyword(ODBC 3)- A warning from
SQLDriverConnect. The Connection succeeds, but theSAVEFILEkeyword was ignored.
The following SQLSTATE codes identify a successful completion condition
where no data has been found that matches the given criteria.
02000 no dataThe "data not found" class identifies completion conditions that were processed without any data that matched the given criteria being found. If the status code is class 02, then the return code will be
SQL_NO_DATA. Most programs do not look for status records if the return code isSQL_NO_DATA, but there is a slight chance that a warning exists. The DBMS does not make a status record forSQLSTATE 02000, but it might make status records for implementation-defined subclasses within class 02.SQLSTATE 02000goes together withsqlcode = +100and return code= SQL_NO_DATA. There are several scenarios which lead toSQLSTATE 02000:- fetches -- If the Cursor position is now past the last row, or before the
first row in the result set -- e.g.: due to a
SQLFetchScroll(...,SQL_PRIOR,...)call when Cursor was on first row of the result set. - updates -- Zero rows were affected by an
INSERT,UPDATEorDELETEstatement. - diagnostics -- No status record corresponds to the
RecordNumberparameter. descfunctions -- No item descriptor area corresponds to theRecordNumberparameter- in general -- Whenever you ask for data, and there is no data.
In the CLI, the DBMS does not generate status records for
SQLSTATE=02000. The only way to check for "no data" is to look at the return code.- fetches -- If the Cursor position is now past the last row, or before the
first row in the result set -- e.g.: due to a
02001 no data-no additional result sets returned- It is possible for a
CALLstatement to produce multiple result sets, but in this case there are no more.02001is possible if the function isSQLMoreResults.
The following SQLSTATE codes identify an exception condition: something is
preventing an SQL statement from being successfully completed.
03000 SQL statement not yet complete- The "SQL statement not yet complete" class identifies exception conditions that relate to incomplete processing of SQL statements.
07000 dynamic SQL error- The "dynamic SQL error" class identifies exception conditions that relate to dynamic SQL processing errors.
07001 dynamic SQL error-using clause does not match dynamic parameters- You might encounter this error if you set the length of a descriptor,
then
EXECUTE ... USING<descriptor>. Often this exception results from consistency-check failure duringSQLExecute: seeSQLSTATE HY021. In ODBC, the name for this subclass is "wrong number of parameters". 07002 dynamic SQL error-using clause does not match target specifications- Often this exception results from consistency-check failure during
SQLExecute: seeSQLSTATE HY021. Sometimes this exception results from an incorrect number of parameters -- but see also:SQLSTATE 07008. In ODBC, the name for this subclass is "COUNTfield incorrect".
07003 dynamic SQL error-cursor specification cannot be executed
07004 dynamic SQL error-using clause required for dynamic parameters- You cannot simply
EXECUTEan SQL statement which has dynamic parameters -- you also need to use aUSINGclause. See also:SQLSTATE 07007. 07005 dynamic SQL error-prepared statement not a cursor-specification- This results from an attempt to use ODBC function
SQLColAttributeorSQLDescribeColfor an SQL statement that returned no result set, or from using "DECLARE CURSOR" followed by a prepare or execute of an SQL statement that does not return a result set. 07006 dynamic SQL error-restricted data type attribute violation- You are using a parameter whose value does not match the <data type>;
the DBMS cannot even try to
CASTto the correct <data type> because the source and target are too different. For example, you have a host variable defined asSQLINTEGER, you have a Column containing aTIMESTAMPand you try to fetch that Column into the host variable. With CLI, this might mean that you forgot to re-bind the parameters when you prepared a new SQL statement. 07007 dynamic SQL error-using clause required for result fields- You cannot simply
EXECUTEan SQL statement which has result fields -- you also need to use aUSINGclause. See also:SQLSTATE 07004. 07008 dynamic SQL error-invalid descriptor count- Using the embedded
SQL ALLOCATE DESCRIPTORstatement, you allocated a 5-item descriptor. Now you are trying to use the sixth item in that descriptor. See also:SQLSTATE 07009. 07009 dynamic SQL error-invalid descriptor index- You are using a CLI descriptor function (such as
SQLBindColorSQLBindParameter) and the Column number is less than 1 or greater than the maximum number of Columns. Or, you are using the embedded SQLALLOCATE DESCRIPTORstatement with a size which is less than 1 or greater than an implementation-defined maximum. See also:SQLSTATE 07008. 07S01 dynamic SQL error-invalid use of default parameter- You used
SQLBindParameterwithSQL_DEFAULT_PARAMETER, but now it turns out that the parameter does not have a default value. 08000 connection exception- The "connection exception" class identifies exception conditions that relate to SQL-Connections.
08001 connection exception-SQL-client unable to establish SQL-connection- The client could not get in touch with the server -- perhaps there is no such server or perhaps the network is busy.
08002 connection exception-connection name in use- The name of an SQL-Connection must be unique. With standard SQL, this
would happen if you said "
CONNECT ... AS 'X' ..." twice (only oneXat a time, please). 08003 connection exception-connection does not exist- You are trying to use a connection-related function (such as
SQLGetConnectAttr) but the SQL-Connection is not open. Or, you said "DISCONNECT 'X'" and eitherXwas never connected, or has already been disconnected. If the call isSQLAllocHandle(SQL_HANDLE_STMT,...),&hstmtis set to zero. You can get diagnostics from thehdbc. 08004 connection exception-SQL-server rejected establishment of SQL-connection- You'll get this error if, for example, the
SQLConnectfunction was unsuccessful. The server might not like the password, or it might already be handling the maximum number of clients. 08006 connection exception-connection failure- This occurs for a
SET CONNECTIONstatement, where the argument is presumably a dormant Connection. The failure might be due to a server failure that occurred while the Connection was dormant. TheSET CONNECTIONmight be implicit -- for example, aDISCONNECTstatement might result in an attempt to re-establish the last dormant Connection. 08007 connection exception-transaction resolution unknown- While you were trying to
COMMIT, you were cut off. This is a bad one, because you are not told whether the transaction finished successfully or not. The ODBC manual calls this error "Connection failure during transaction" and implies that it can happen forROLLBACKtoo. 08S01 connection exception-communication link failure(ODBC 2+3)- This can happen during execution of pretty well any ODBC function. Perhaps there was a hiccup on a phone line.
09000 triggered action exception- The "triggered action exception" class identifies exception conditions that relate to Triggers.
0A000 feature not supported- The "feature not supported" class identifies exception conditions that
relate to features you're trying to use, but that your DBMS hasn't
implemented. The Standard does not specify what will cause this
SQLSTATE, possibly because the expectation is that all features will be supported. If the feature is ODBC-related, see also:SQLSTATE IM001,HYC00. 0A001 feature not supported-multiple server transactions- The meaning is "a single transaction cannot be performed on multiple servers". Such a feature is sophisticated and rare.
0B000 invalid transaction initiation- The "invalid transaction initiation" class identifies exception conditions that relate to beginning a transaction.
0D000 invalid target type specification- The "invalid target type specification" class identifies exception conditions that relate to specifying a target for data.
0E000 invalid schema name list specification- The "invalid schema name list specification" class identifies exception conditions that relate to specifying Schema paths.
0F000 locator exception- The "locator exception" class identifies exception conditions that
relate to locators:
BLOBandCLOB<data type>s, and their values. 0F001 locator exception-invalid specification- This will be returned if a value passed for a
BLOBorCLOBis invalid.
0F002 locator exception-update attempted with non-updatable locator
0F003 locator exception-location does not represent specified object
0F004 locator exception-unknown native value
0G000 reference to null table value
0H000 invalid SQLSTATE value
0K000 resignal when handler not active
0K002 resignal when handler not active-modifying SQL-data not permitted
0K003 resignal when handler not active-prohibited SQL-statement attempted
0K005 resignal when handler not active-function executed no return statement
0L000 invalid grantor
0N000 most specific type mismatch in invocation of type-preserving function
0P000 invalid role specification
0Q000 source result set not created by current SQL-server
0R000 cursor already allocated to result set or procedure
20000 case not found for case statement
21000 cardinality violation- Suggested error message: "subquery contained more than one row". For
example, suppose you have a Table T, with a Column S1 and two rows. In
both rows, Column S1 has the value 5. Then either "
SELECT (SELECT s1 FROM T) FROM ..." (scalar subquery) or "... WHERE 5 = (SELECT s1 FROM T)" (row subquery) violate cardinality. Another possibility, applicable to embedded SQL only, is that you are using a singleton-SELECTstatement format but there are two rows returned. Some cardinality violations, e.g.:OVERLAPSoperand with degree greater than 2, causeSQLSTATE=42000instead ofSQLSTATE=21000. 21S01 cardinality violation-insert value list does not match column list(ODBC 2+3)- For example: the statement "
INSERT INTO T (a,b) VALUES (1,2,3)" is trying to insert three values into two Columns. 21S02 cardinality violation-degree of derived table does not match column list(ODBC 2+3)- For example: the SQL statement "
CREATE VIEW (a,b) AS SELECT a,b,c FROM T;" is creating a 2-Column View for a 3-Column select. 22000 data exception- The "data exception" class identifies exception conditions that relate to data errors.
22001 data exception-string data, right truncation- Suppose you try to insert a 5-character string into a Column defined as
CHAR(4), or suppose you use the expression "CAST (12345 AS CHAR(4))". No truncation actually occurs since the SQL statement fails. See also:SQLSTATE 01004. 22002 data exception-null value, no indicator parameter- Suggested error message: "
NULLseen, host program passed no indicator". For example, you usedSQLBindCol, but passed no parameter for an indicator value to be returned to. This is not an error unless you fetch aNULL. 22003 data exception-numeric value out of range- Suggested error message: "the numeric value <> is too big to fit in the
target <>". Often this is the result of an arithmetic overflow -- for
example, "
UPDATE ... SET SMALLINT_COLUMN = 9999999999", or you're trying to retrieve a value of 5 billion into a host variable defined in Pascal as "Word". Fractional truncation won't cause this error, seeSQLSTATE 01S07.
22004 data exception-null value not allowed
22005 data exception-error in assignment- For
GET DESCRIPTORandSET DESCRIPTORstatements, where the <data type> and size indicated in the descriptor does not match the value, this error appears. 22006 data exception-invalid interval format- For example, a year-month interval should contain only a year integer, a
'-' separator, and a month integer. See also:
SQLSTATE 22015. 22007 data exception-invalid datetime format- Suggested message: "For the <data type> <>, <> is not a valid value".
This error only occurs if there is an explicit or implicit
CASTto a datetime (date or time or timestamp). See also:SQLSTATE 22008,22018. 22008 data exception-datetime field overflow- Suggested message: "For the data type <>, <> is not a valid value". One
thing to look for: arithmetic which causes the
DAYfield of a date to be greater than the last day of the month -- for exampleDATE '1994-03-31' + INTERVAL '01' MONTH. See also:SQLSTATE 22007. 22009 data exception-invalid time zone displacement value- Suggested message: "The time zone displacement value <> is outside the
range -12:59 to 13:00". This could happen for
SET LOCAL TIME ZONE INTERVAL '22:00' HOUR TO MINUTE;, or forTIMESTAMP '1994-01-01 02:00:00+10:00'. (In the latter case, it is the result of the calculation that is a problem.)
2200A data exception-null value in reference target
2200B data exception-escape character conflict
2200C data exception-invalid use of escape character
2200D data exception-invalid escape octet
22010 data exception-invalid indicator parameter value- The value of the indicator variable is less than zero but is not equal
to -1 (
SQL_NULL_DATA). 22011 data exception-substring error- Suggested message: "The maximum length of
SUBSTRINGparameter is <>". For example, "... SUBSTRING (string_column FROM 5 FOR 100) ..." when the length ofSTRING_COLUMNis only 1. 22012 data exception-division by zero- For example: "
... column_name / ? ...", where?is a parameter marker, and the value of the parameter at run time is 0. If the Column containsNULL, then the result isNULL-- the Standard makes it clear that dividingNULLby zero is not an error.
22014 data exception-invalid update value
22015 data exception-interval field overflow- Suggested message: "The <> field contains <>, the maximum is <>". For
example, "
... DATE '1993-01-01' + INTERVAL '1000' YEAR ..." (this is a tricky one -- the default size of all interval fields including year fields is only 2 digits). See also:SQLSTATE 22006. 22018 data exception-invalid character value for cast- Suggested message: "The character <> cannot be used when
CAST``ing to data type <>". For example, if you try to cast ``'1994/10/10'to a date, it won't work because the separator is '/' (the correct separator is '-'). 22019 data exception-invalid escape character- Suggested message: "The
LIKEescape value <> is longer than 1 character". The expression "... LIKE '...' ESCAPE 'AB' ..." would return this error.
2201B data exception-invalid regular expression
2201C data exception-null row not permitted in table
22020 data exception-invalid limit value
22021 data exception-character not in repertoire- Suggested message: "The character <> is not in the repertoire of
Character set <>". For example, the Character set
SQL_CHARACTERdoes not contain the tilde (~), so this <literal> is not allowed: "... _SQL_CHARACTER '~' ...". 22022 data exception-indicator overflow- Suggested message: "indicator is too small for size value <>". This could happen if you use embedded SQL and you define the indicator as a C "short int" or Pascal "Word". If you use ODBC, then the message won't happen because all indicators must be 32-bit.
22023 data exception-invalid parameter value
22024 data exception-unterminated C string- Suggested message: "the C parameter string starting with <> is too
long". For example, an SQL statement uses a
?parameter, for a string, but at runtime it is seen that the C char-string does not have a terminating'\0'. The DBMS can only detect this error if it knows what the maximum string size is, i.e.: only in embedded SQL. Usually this problem will appear as a too-long or improperly-formatted string, so several otherSQLSTATEerror returns are possible -- for example.SQLSTATE 22019. 22025 data exception-invalid escape sequence- Suggested message: "
LIKEpattern <> has invalid escape sequence <>". If you use an escape character, it must be followed in the pattern by _ or % or another escape character. If you use "... LIKE 'X%@' ESCAPE '@' ...", you'll get this error. 22026 data exception-string data, length mismatch- With ODBC this error should only occur for
SQL_LONGVARCHARorSQL_LONGVARBINARYstrings. For standard SQL, this error should only occur for bit strings. 22027 data exception-trim error- Suggested message: "the
TRIMstring <> is longer than 1 character". For example, "... TRIM('AB' FROM '...') ..." results in this error.
22028 data exception-row already exists
2202C data exception-sublist error
2202D data exception-null instance used in mutator function
2202E data exception-array element error
2202F data exception-array data, right truncation
23000 integrity constraint violation- The "integrity constraint violation" class identifies exception
conditions that relate to Constraint violations. Suggested message for
SQLSTATE 23000: "Attempted violation of constraint <>". For example, Table T has aPRIMARY KEYConstraint and you attempt to insert two rows into T, both with precisely the same values in all Columns. For SQL-92, thisSQLSTATEapplies to attempted violations of any kind of Constraint, includingNOT NULLs andFOREIGN KEYConstraints. The message can also occur if the total length of a foreign key Column list is exceeded. See also:SQLSTATE 40002.
23001 integrity constraint violation-restrict violation
24000 invalid cursor stateThe "invalid cursor state" class identifies exception conditions that relate to Cursors. For
SQLSTATE 24000, the Cursor-related operation can't happen because some preliminary function hasn't been called or hasn't been completed -- for example:OPEN<Cursor>, then immediately try toOPEN<Cursor> again.FETCHwithout opening the Cursor.OPEN<Cursor>, forget toFETCH, thenDELETE ... WHERE CURRENT OF<Cursor>.
For CLI programs, the DBMS returns
SQLSTATE=24000if you try toFETCHand there is no result set (for example, because the previous SQL statement wasINSERT). However, if there was no previous SQL statement at all, then the return is not24000butHY010(CLI-specific error-function sequence error).25000 invalid transaction state- The "invalid transaction state" class identifies exception conditions
that relate to transactions. For
SQLSTATE 25000, you are most likely trying to execute an SQL statement that can only be executed at transaction start -- for example you are issuing aSET SESSION AUTHORIZATIONstatement after selecting something. Alternatively, you specifiedSET TRANSACTION READ ONLYand now you are sayingUPDATE,DROP, etc. Finally, it is possible you are sayingINSERTafter aFETCH. 25001 invalid transaction state-active SQL-transactionSTART TRANSACTIONorDISCONNECTorSET SESSION AUTHORIZATIONorSET ROLEstatements cannot be issued if a transaction has already been started.25002 invalid transaction state-branch transaction already activeSET TRANSACTION LOCAL ..., which applies only in multiple-server contexts, is illegal if a local transaction is already happening.
25003 invalid transaction state-inappropriate access mode for branch
transaction
25004 invalid transaction state-inappropriate isolation level for branch
transaction
25005 invalid transaction state-no active SQL-transaction for branch
transaction
25006 invalid transaction state-read-only SQL-transaction
25007 invalid transaction state-schema and data statement mixing not supported- Some DBMSs do not allow SQL-Schema statements (such as
CREATE) to be mixed with SQL-data statements (such asINSERT) in the same transaction. 25008 invalid transaction state-held cursor requires same isolation level- The
SET TRANSACTIONstatement cannot be used to change isolation level if there is a held Cursor made with a different isolation level left over from the last transaction. 25S01 invalid transaction state-transaction state unknown(ODBC 3)- The attempt to end the transaction (with
SQLEndTran) failed for at least one of the environment's Connections. 25S02 invalid transaction state-transaction is still active(ODBC 3)- The attempt to end the transaction (with
SQLEndTran) failed; the transaction did not end (that is, the transaction is not rolled back). 25S03 invalid transaction state-transaction is rolled back(ODBC 3)- The attempt to end the transaction (with
SQLEndTran) failed; the transaction is rolled back (that is, the transaction ended). 26000 invalid SQL statement name- Probable cause: you failed to
PREPAREan SQL statement and now you are trying toEXECUTEit. 27000 triggered data change violation- With SQL-92, you can cause this error with interlocked
FOREIGN KEYConstraints thatCASCADE ON UPDATE, so that when youUPDATErow#1 inTABLE#1, it causes anUPDATEto row#2 inTABLE#2, which in turn causes anUPDATEto row#1 inTABLE#1-- and that's an error because the Standard doesn't allow this kind of looping. With SQL3, this error can also happen for Triggers. See also:SQLSTATE 09000,40004. 28000 invalid authorization specification- This error is caused by an invalid <AuthorizationID>. For example,
"
SET SESSION AUTHORIZATION 'PUBLIC'" is illegal because'PUBLIC'has a special significance in SQL. It's implementation-defined whether this can happen due to an entry of the wrong password. 2A000 direct SQL syntax error access or rule violation- This error does not appear in ordinary programs.
2B000 dependent privilege descriptors still exist- You used "
REVOKE GRANT OPTION FOR", but notCASCADE. 2C000 invalid character set name- Presumably an invalid <Character set name> would be one that begins with a digit, contains a non-Latin letter, etc.
2D000 invalid transaction termination- Has to do with savepoints and atomicity of transactions. Should not be a matter of concern until SQL3 gets going.
2E000 invalid connection name- For a
CONNECTstatement, the argument must be a valid <identifier>. 2F000 SQL routine exception- An SQL routine is a procedure or function which is written in SQL.
SQLSTATEclass2Fidentifies exception conditions that relate to SQL routines. (Exceptions for non-SQL routines are class38.) 2F002 SQL routine exception-modifying SQL-data not permitted- The probable cause of this error is that the
CREATE PROCEDUREorCREATE FUNCTIONstatement contained the clause:CONTAINS SQLorREADS SQL, but the function contains an SQL statement which can modify the database (for example, anUPDATEstatement). The corresponding external-routine exception is38002. 2F003 SQL routine exception-prohibited SQL-statement attempted- The prohibited procedural SQL statements are the SQL-transaction
statements (
START TRANSACTION,SET TRANSACTION,SET CONSTRAINTS,CREATE SAVEPOINT,RELEASE SAVEPOINT,COMMIT,ROLLBACK) or the SQL-Connection statements (CONNECT,SET CONNECTION,DISCONNECT) or the SQL-Schema statements (CREATE,DROP,ALTER,GRANT,REVOKE). The corresponding external-routine exception is38003. 2F004 SQL routine exception-reading SQL-data not permitted- The probable cause of this error is that the
CREATE PROCEDUREorCREATE FUNCTIONstatement contains the clause:CONTAINS SQL, but the function contains an SQL statement which reads the database (for example, aSELECTstatement). The corresponding SQL-routine exception is38004.
2F005 SQL routine exception-function executed no return statement
30000 invalid SQL statement
31000 invalid target specification value
33000 invalid SQL descriptor name- If, in embedded SQL, you use "
EXECUTE ... USING DESCRIPTOR 'X';", a descriptor namedXmust exist. 34000 invalid cursor name- If the function is
SQLSetCursorName, then the problem is that a <Cursor name> must be a unique, valid <identifier>. If the function isSQLPrepareorSQLExecDirect, the SQL statement is "UPDATE ... WHERE CURRENT OF<Cursor>" or "DELETE ... WHERE CURRENT OF<Cursor>" and <Cursor> is not the name of an open Cursor. 35000 invalid condition number- With embedded SQL, you get this by saying "
GET DIAGNOSTICS EXCEPTION 0". With the CLI, you get this by callingSQLGetDiagRecorSQLGetDiagFieldwith aRecordNumberparameter less than 1. IfRecordNumberis greater than the number of status records, you don't get this error. Instead, you get anSQL_NO_DATAreturn code. 36000 cursor sensitivity exception- The "cursor sensitivity exception" class identifies exception conditions that relate to Cursors and their sensitivity attribute.
36001 cursor sensitivity exception-request rejected- An attempt was made to open a sensitive Cursor, but the DBMS cannot guarantee that data changes will be visible throughout the transaction.
36002 cursor sensitivity exception-request failed- For example, an attempt was made to execute a positioned
DELETEstatement, but there is a sensitive Cursor open, and (for some implementation-dependent reason) the effects of theDELETEcannot be made visible via that Cursor. 37000 dynamic SQL syntax error or access rule violation- The SQL-92 Standard originally mentioned this
SQLSTATE, but according to a later correction (corrigendum bulletin #3) we should useSQLSTATE = 42000instead. That is what all ODBC 3.x drivers do. 38000 external routine exception- An external routine is a procedure or function which is written in a
language other than SQL.
SQLSTATEclass38identifies exception conditions that relate to external routines. (Exceptions from SQL routines are class2F.) 38001 external routine exception-containing SQL not permitted- The probable cause is that the
CREATE PROCEDUREorCREATE FUNCTIONstatement contained the clause:NO SQL, but the routine contains an SQL statement. 38002 external routine exception-modifying SQL-data not permitted- The probable cause is that the
CREATE PROCEDUREorCREATE FUNCTIONstatement contained the clause:NO SQLorCONTAINS SQLorREADS SQL, but the function contains an SQL statement which can modify the database (for example, anUPDATEstatement). 38003 external routine exception-prohibited SQL-statement attempted- The prohibited procedural SQL statements are the SQL-transaction
statements (
START TRANSACTION,SET TRANSACTION,SET CONSTRAINTS,CREATE SAVEPOINT,RELEASE SAVEPOINT,COMMIT,ROLLBACK) or the SQL-Connection statements (CONNECT,SET CONNECTION,DISCONNECT) or the SQL-Schema statements (CREATE,DROP,ALTER,GRANT,REVOKE). 38004 external routine exception-reading SQL-data not permitted- The probable cause is that the
CREATE PROCEDUREorCREATE FUNCTIONstatement contained the clause:NO SQLorCONTAINS SQL, but the function contains an SQL statement which reads the database (for example, aSELECTstatement).
39000 external routine invocation exception
39001 external routine invocation exception-invalid sqlstate returned
39004 external routine invocation exception-null value not allowed
3B000 savepoint exception
3B001 savepoint exception-invalid specification
3B002 savepoint exception-too many
3C000 ambiguous cursor name- A more appropriate wording is: duplicate <Cursor name>. In ODBC you can
get this by calling
SQLSetCursorNamewith an argument that is the name of an already-open Cursor. 3D000 invalid catalog name- Presumably a <Catalog name> could be invalid if it is used as a
qualifier or as the argument of
SET CATALOG, and does not refer to an existing Catalog or is not a valid <identifier>. However, all those situations are equally covered bySQLSTATE=42000(syntax error or access violation). ForSQLSetConnectAttr, the problem is with aSQL_ATTR_CURRENT_CATALOGspecification. 3F000 invalid schema name- Presumably a <Schema name> could be invalid if it is used as a qualifier
or as the argument of
SET SCHEMA, and does not refer to an existing Schema or is not a valid <identifier>. However, all those situations are equally covered bySQLSTATE=42000(syntax error or access violation).
3G000 invalid UDT instance
40000 transaction rollback
40001 transaction rollback-serialization failure- Two SQL jobs are running simultaneously, and a concurrency problem arose. For example, using a locking protocol, there was a deadlock or, using a timestamp protocol, a younger job has read the Object.
40002 transaction rollback-integrity constraint violation- This occurs for
COMMIT, if there were deferred Constraints (deferred Constraints aren't checked untilCOMMITtime unlessSET CONSTRAINTS IMMEDIATEis executed). So: you asked forCOMMIT, and what you got wasROLLBACK. See also:SQLSTATE 23000. 40003 transaction rollback-statement completion unknown- The SQL-Connection was lost during execution of an SQL statement.
40004 transaction rollback-triggered action exception- This occurs for
COMMIT, if there was a deferred Constraint -- presumably aFOREIGN KEYConstraint unless Triggers are supported by the DBMS -- and there was an attempt to violate the Constraint. See also:SQLSTATE 09000,27000. 42000 syntax error or access rule violationThe favourite exception. Syntax errors include not just grammar or spelling errors, but "bind problems" such as failure to find an Object. Access violations are due to lack of Privileges. A high security DBMS will try to hide from the user whether the problem is "you don't have access to
X" as opposed to "Xisn't there"; that's why these two different categories are lumped together in oneSQLSTATE(thus users can't discover what the <Table name>s are by trying out all the possibilities).Caution!
It's easy to think that a syntax violation will always be caught during the prepare stage. Not so. Many DBMSs don't bind until the execution stage. You have to check after both
SQLPrepareandSQLExecute, and perhaps even afterSQLFetch(because a DBMS may evaluate expressions in the select list atFETCHtime, or a Column might have been dropped since the Cursor was opened).42S01 syntax error or access rule violation-base table or view already exists(ODBC 3)- This is caused by something like "
CREATE TABLE T ..." when there's already a Table named T. 42S02 syntax error or access rule violation-base table or view not found(ODBC 3)- This is caused by something like "
SELECT * FROM T;" when there's no Table named T. 42S11 syntax error or access rule violation-index already exists(ODBC 3)- This is caused by something like "
CREATE INDEX I ON T(c);" when there's already an index named I. 42S12 syntax error or access rule violation-index not found(ODBC 3)- This is caused by something like "
DROP INDEX I;" when there's no index named I. 42S21 syntax error or access rule violation-column already exists(ODBC 3)- This is caused by something like "
ALTER TABLE T ADD COLUMN c ..." when Column C already exists. 42S22 syntax error or access rule violation-column not found(ODBC 3)- This is caused by something like "
SELECT c FROM T;" when Table T has no Column named C. 44000 with check option violation- This is caused by something like "
CREATE VIEW V AS SELECT x FROM T WHERE x=5 WITH CHECK OPTION;" then "UPDATE V SET x = 6;". The View'sWITH CHECK OPTIONclause is violated by the attemptedUPDATE, which fails.
45000 unhandled user-defined exception
70100 operation aborted(ODBC 2)- Possible because tasks or threads can be destroyed in some operating systems, but don't expect to see this.
H1zzz SQL Multimedia part 1
H2zzz SQL Multimedia part 2
H3zzz SQL Multimedia part 3
H4zzz SQL Multimedia part 4
H5zzz SQL Multimedia part 5
H6zzz SQL Multimedia part 6
H7zzz SQL Multimedia part 7
H8zzz SQL Multimedia part 8
H9zzz SQL Multimedia part 9
HAzzz SQL Multimedia part 10
HBzzz SQL Multimedia part 11
HCzzz SQL Multimedia part 12
HDzzz SQL Multimedia part 13
HEzzz SQL Multimedia part 14
HFzzz SQL Multimedia part 15
HY000 CLI-specific condition-invalid handle
CLI-specific condition-dynamic parameter value neededThere is no status record for the invalid-handle exception. The return from the CLI function is -2 (
SQL_INVALID_HANDLE), so the only test for invalid-handle is:if (sqlreturn == SQL_INVALID_HANDLE) ...
The "invalid handle" exception occurs if (a) the passed
hstmtorhdbcorhenvorhdescis not a handle of any resource at all or (b) the passed handle refers to the wrong type of resource, for example you passed ahdescbut ahdbcwas expected in this context.There is no status record for the need-data exception either. The return from the CLI function is +99 (
SQL_NEED_DATA), so the only test for need-data is:if (sqlreturn == SQL_NEED_DATA) ...
This exception is associated with deferred parameters.
HY001 CLI-specific condition-memory allocation error- Probable cause: a malloc failure. One possible solution is to close all
other windows. If
SQLAllocHandle(ENVIRONMENT HANDLE ...): the DBMS returns 0 to&henv. Since there is no valid handle, you can't get diagnostics. IfSQLAllocHandle(CONNECTION HANDLE ...): the DBMS returns 0 to&hdbc. You can get diagnostics using thehenv.
HY002 CLI-specific condition-link-to-result-sets attribute precludes using this routine
HY003 CLI-specific condition-invalid data type in application descriptor- Actually, the invalid <data type> is not in an application descriptor,
but in the parameter of a CLI function (
SQLBindCol,SQLBindParameter,SQLGetData,SQLGetParamData). HY004 CLI-specific condition-invalid data type- The
SQLGetTypeInfofunction requires aDataTypeparameter whose value is eitherSQL_ALL_TYPESor one of the "concise type" codes. If theDataTypeparameter has an invalid value, you get this error.SQLSetDescFieldandSQLBindParameterparameters must also contain "concise type" codes. HY007 CLI-specific condition-associated statement is not prepared- A function (for example
SQLGetDescField) requires a descriptor field, but the SQL statement has not been prepared so no description exists. HY008 CLI-specific condition-operation cancelled- Many functions can operate asynchronously. Such operations can be
cancelled using the
SQLCancelfunction. That's what happened to this one. HY009 CLI-specific condition-invalid use of null pointer- One of the parameters for a function is a pointer (address). The passed pointer (address) is 0000:0000, which isn't acceptable. Some DBMSs will return this error if they detect that the host language can't handle pointers.
HY010 CLI-specific condition-function sequence error- Some functions won't work unless some other function has successfully
executed. For example, it's impossible to "fetch" if you've never
connected or selected. Or, an asynchronously executing function has not
finished. Or, the last
SQLExecDirectorSQLExecDirectcall returnedSQL_NEED_DATA(meaning the SQL statement has not finished executing), and you're trying to free thestmt. See also:SQLSTATE 24000. HY011 CLI-specific condition-attribute cannot be set now- Some settings cannot be changed in the middle of a transaction. For
example, you can't call the function
SQLSetConnectAttrto changeSQL_ATTR_TXN_ISOLATION, after you've already done some inserts. HY012 CLI-specific condition-invalid transaction operation code- For the function
SQLEndTran, the only possible arguments areSQL_COMMITandSQL_ROLLBACK. HY013 CLI-specific condition-memory management error- Many functions can return this. Usually the reason is "low memory conditions".
HY014 CLI-specific condition-Limit on number of handles exceededThis can come from a routine that allocates a handle (
env,dbc,stmt,desc) such asSQLAllocHandle. The maximum number of handles is implementation-defined for each type.- If
SQLAllocHandle(SQL_HANDLE_ENV,NULL,&henv): the DBMS puts a handle in&henvdespite the error; however, the handle is just a skeleton -- you won't be able to use it to allocate a connection handle with. - If
SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc): the DBMS puts 0 in&hdbc(SQL_NULL_HDBC). You can get diagnostics using thehenv. - If
SQLAllocHandle(SQL_HANDLE_STMT,hdbc,&hstmt): the DBMS puts 0 in&hstmt(SQL_NULL_HSTMT). You can get diagnostics using thehdbc. - If
SQLAllocHandle(SQL_HANDLE_DESC,hdbc,&hdesc): the DBMS puts 0 in&hdesc(SQL_NULL_HDESC). You can get diagnostics using thehdbc.
- If
HY015 CLI-specific condition-no cursor name available- Obsolete -- happens only for ODBC 2.x drivers, when you call
SQLGetCursorName. HY016 CLI-specific condition-cannot modify an implementation row descriptor- The target of a function (for example
SQLCopyDesc) was an IRD, which can't be changed. HY017 CLI-specific condition-invalid use of an automatically allocated descriptor handle- An attempt was made to free or change a descriptor which was not made by the application program.
HY018 CLI-specific condition-Server declined cancel request- The ODBC function
SQLCancelwas called; it's up to the data source to decide whether this can be processed. For example, the data source might not be responding to the driver manager's requests. HY019 CLI-specific condition-non-character and non-binary data sent in pie ces- The function
SQLPutDatawas called twice for the same parameter or Column; this is only allowed for character and binary data. HY020 CLI-specific condition-attempt to concatenate a null value- The function
SQLPutDatawas called twice for the same parameter or Column; in one of the calls, the passed value wasNULL. HY021 CLI-specific condition-Inconsistent descriptor information- The fields of a
deschave failed the consistency check. For example, theSQL_DESC_SCALEvalue is greater than theSQL_DESC_PRECISIONvalue (for aDECIMALfield) or theSQL_DESC_TYPEvalue isSQL_DATETIMEbut theSQL_DESC_INTERVAL_CODEvalue is 6 (only 1 to 5 would be legal). This error happens only for the function callsSQLSetDescFieldandSQLSetDescRec. For other functions, inconsistency causesSQLSTATE 07001or07002. HY024 CLI-specific condition-invalid attribute value- One of the "attribute" functions was called (
SQLGetEnvAttr,SQLSetEnvAttr,SQLGetConnectAttr,SQLSetConnectAttr,SQLGetStmtAttr,SQLSetStmtAttr). The numeric value for the attribute parameter for this function is not defined.
HY055 CLI-specific condition-non-string data cannot be used with string
routine
HY090 CLI-specific condition-invalid string length or buffer length- You called any CLI function that passes a string value. The size
parameter for this string value was less than or equal to zero, and was
not equal to -3 (
SQL_NTS). HY091 CLI-specific condition-invalid descriptor field identifier- A descriptor is a structure with information about a selected Column (in
a result set); a field in that descriptor is usually identified by a
numeric code; the number you used was out of bounds. For example, you
can't call
SQLColAttributewith a field identifier parameter = 0. HY092 CLI-specific condition-invalid attribute/option identifier- You called any CLI function that passes an option number (for example
SQLGetConnectAttr). The value you passed was not one of the defined values. HY095 CLI-specific condition-Function type out of range(ODBC 3)- The
SQLGetFunctionsfunction was called, with aFunctionIdparameter, the value of which is not defined for ODBC. ThisSQLSTATEis not mentioned in the SQL3 Standard. HY103 CLI-specific condition-invalid retrieval code(ODBC 3)- The ODBC function
SQLDataSourcesorSQLDriverswas called, with aDirectionparameter, the value of which does not equalSQL_FETCH_FIRST,SQL_FETCH_NEXT, etc. HY104 CLI-specific condition-invalid precision or scale value- The maximum precision or scale for some <data type>s is up to the data
source (i.e. sometimes the driver can't handle big things), so the
SQLBindParameterfunction gets this return. Try querying the data source to find out what its maxima are. HY105 CLI-specific condition-invalid parameter mode- The function call (e.g.:
SQLBindParameter) contains anInputOutputModeparameter, the value of which is not one of:SQL_PARAM_MODE_IN,SQL_PARAM_MODE_OUT,SQL_PARAM_MODE_INOUT. HY106 CLI-specific condition-invalid fetch orientation- Only certain fetch "orientations" are allowed (e.g.:
NEXT,FIRST,LAST,PRIOR,ABSOLUTE,RELATIVE). The value you passed wasn't one of them, for the functionSQLFetchScroll. Or, if the Cursor isn't aSCROLLCursor, the only legal orientation isNEXT. ODBC variations: this could also happen forSQLExtendedFetch, and the name for thisSQLSTATEis: Fetch type out of range. HY107 CLI-specific condition-Row value out of range- One of the ODBC "fetch" or "set position" functions was called (e.g.:
SQLFetch) and the Cursor is "key set driven", but the row involved isn't in the key set's range. HY109 CLI-specific condition-invalid cursor position- A row could not be fetched, probably because it has been deleted or because it is now locked.
HY110 CLI-specific condition-invalid driver completion(ODBC 3)- The ODBC function
SQLDriverConnectcontains aDriverCompletionparameter, the value of which is not defined for ODBC. ThisSQLSTATEis not mentioned in the SQL Standard. HY111 CLI-specific condition-invalid bookmark value(ODBC 3)- The ODBC function
SQLExtendedFetchorSQLFetchScrollwas called, with aFetchOrientationparameter, the value of which was not defined for ODBC, or was a null pointer. ThisSQLSTATEis not mentioned in the SQL Standard. HYC00 CLI-specific condition-optional feature not implemented(ODBC 3)- Many of the ODBC functions have optional features. It is unlikely that
any driver will support every optional feature. When the driver doesn't,
this is the error you'll get. See also:
SQLSTATE 0A000(which applies to unimplemented features outside the CLI) andSQLSTATE IM001(which applies to unsupported ODBC functions rather than features). The ODBC manual refers toHYC00as "particularly significant". HYT00 CLI-specific condition-timeout expired(ODBC 3)- You can specify a timeout value in milliseconds (with the
SQLSetStmtAttrODBC function call). If the timeout value that you set goes by and the statement is unfinished, this return happens. HYT01 CLI-specific condition-connection timeout expired(ODBC 3)- This is similar to
HYT00, but it applies to the connection rather than to the statement. HZzzz Remote Database Access- The Remote Database Access standard, ISO/IEC 9579-2, defines several subclass code values which may be passed on via SQL, but are not defined within SQL. These will all be in the class HZ.
IM001 driver does not support this function(ODBC 2+3)- There are a lot of ODBC functions. Some drivers don't support them all,
especially since ODBC 3.x is still new (and Microsoft keeps changing
it). So this error comes from the driver. Compare
SQLSTATE HYC00. IM002 Data source name not found and no default driver specified(ODBC 2+3)- This happens when you're connecting with ODBC, and there's no DSN registered.
IM003 specified driver could not be loaded(ODBC 2+3)- Possibly the driver's DLL is missing, or is not in the directory that the driver manager is searching.
IM004 driver's SQLAllocHandle on SQL_HANDLE_ENV failed(ODBC 2+3)- Usually this would indicate low memory, or that the maximum number of handles is exceeded, or a problem with function sequence.
IM005 driver's SQLAllocHandle on SQL_HANDLE_DBC failed(ODBC 2+3)- Usually this would indicate low memory, or that the maximum number of handles is exceeded, or a problem with function sequence.
IM006 driver's SQLSetConnectAttr failed(ODBC 2+3)- A connection error (during
SQLBrowseConnectorSQLConnectorSQLDriverConnect). IM007 no data source or driver specified; dialog prohibited(ODBC 2+3)- An error return from the ODBC function call
SQLDriverConnect. IM008 dialog failed(ODBC 2+3)- The
SQLDriverConnectfunction puts up a dialog box; presumably the user did not end with "OK". IM009 unable to load translation DLL(ODBC 2+3)- A failure during connect or during
SQLSetConnectAttr, probably due to a missing DLL, which may indicate an installation error. IM010 data source name too long(ODBC 3)- The ODBC connection functions (
SQLBrowseConnectorSQLConnectorSQLDriverConnect) have a maximum size for the name of the data source (DSN). You've exceeded it. IM011 driver name too long(ODBC 3)- The
SQLBrowseConnectandSQLDriverConnectfunctions have a maximum size for the name of the driver. You've exceeded it. IM012 driver keyword syntax error(ODBC 3)- The
SQLBrowseConnectorSQLDriverConnectfunctions require data in a fixed format. IM013 trace file error(ODBC 3)- Couldn't perform an operation on the trace file, perhaps a failure to write because of a disk-full situation.
IM014 invalid name of file DSN(ODBC 3)- The
SQLDriverConnectfunction requires a valid identifier. IM015 corrupt file data source(ODBC 3)- The
SQLDriverConnectfunction can't read the file.
OH000 invalid SQLSTATE value
OK000 resignal when handler not active
And that's it for CLI diagnostics. In the next chapter, we'll take a look at some general functions.