次の方法で共有


ODBC エラーの処理 (ODBC)

2 つの ODBC 関数呼び出し SQLGetDiagRec および SQLGetDiagField を使用すると、ODBC メッセージを取得できます。 SQLStatepfNative、および ErrorMessage の各診断フィールドの主要な ODBC 関連情報を取得するには、SQL_NO_DATA が返されるまで SQLGetDiagRec を呼び出します。 診断レコードごとに、SQLGetDiagField を呼び出して個々のフィールドを取得できます。 ドライバー固有のフィールドはすべて、SQLGetDiagField を使用して取得する必要があります。

SQLGetDiagRec および SQLGetDiagField は、個々のドライバーではなく、ODBC ドライバー マネージャーによって処理されます。 ODBC ドライバー マネージャーでは、接続が正しく確立されるまでドライバー固有の診断フィールドをキャッシュしません。 接続が正しく確立される前に、ドライバー固有の診断フィールドに対して SQLGetDiagField を呼び出すことはできません。 これには、SQL_SUCCESS_WITH_INFO が返される場合の ODBC 接続コマンドも含まれます。 ドライバー固有の診断フィールドは、次の ODBC 関数呼び出しまで使用できません。

説明

このサンプルでは、SQLGetDiagRec を呼び出して標準的な ODBC 情報を取得する簡単なエラー ハンドラーを示します。 このサンプルでは有効な接続を調べ、有効な接続がある場合は、SQLGetDiagField を呼び出して SQL Server ODBC ドライバー固有の診断フィールドを取得します。このサンプルは、IA64 ではサポートされません。

このサンプルは、ODBC 3.0 以降のバージョン用に開発されました。

セキュリティに関する注意セキュリティに関する注意

可能な場合は、Windows 認証を使用します。 Windows 認証が使用できない場合は、実行時に資格情報を入力するようユーザーに求めます。 資格情報をファイルに保存するのは避けてください。 資格情報を保存する必要がある場合は、Win32 Crypto API を使用して暗号化してください。

AdventureWorks と呼ばれる ODBC データ ソース (既定のデータベースは AdventureWorks サンプル データベース) が必要です (AdventureWorks サンプル データベースは、Microsoft SQL Server のサンプルとコミュニティのプロジェクトのホーム ページからダウンロードできます)。このデータ ソースには、オペレーティング システムに用意されている ODBC ドライバーが使用されている必要があります (ドライバー名は "SQL Server")。 このサンプルを 64 ビット オペレーティング システムで 32 ビット アプリケーションとしてビルドし、実行する場合、%windir%\SysWOW64\odbcad32.exe の ODBC アドミニストレーターを使用して ODBC データ ソースを作成する必要があります。

このサンプルでは、コンピューターの既定の SQL Server インスタンスに接続します。 名前付きインスタンスに接続するには、ODBC データ ソースの定義を変更し、server\namedinstance 形式でそのインスタンスを指定します。 SQL Server Express は、既定で名前付きインスタンスとしてインストールされます。

1 つ目の (Transact-SQL) コード リストを実行して、このサンプルで使用するストアド プロシージャを作成します。

odbc32.lib を使用して 2 つ目の (C++) コード リストをコンパイルします。 次に、プログラムを実行します。

3 つ目の (Transact-SQL) コード リストを実行して、このサンプルで使用したストアド プロシージャを削除します。

コード

use AdventureWorks
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'BadOne')
   DROP PROCEDURE BadOne

Go

CREATE PROCEDURE BadOne 
AS 
SELECT * FROM Purchasing.Vendor
Go

コード

// compile with: odbc32.lib
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>

#define MAXBUFLEN 256

SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;     
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;

void ProcessLogMessages(SQLSMALLINT plm_handle_type, SQLHANDLE plm_handle, char *logstring, int ConnInd);

void Cleanup() {
   if (hstmt1 != SQL_NULL_HSTMT)
      SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);

   if (hdbc1 != SQL_NULL_HDBC) {
      SQLDisconnect(hdbc1);
      SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
   }

   if (henv != SQL_NULL_HENV)
      SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

int main() {
   RETCODE retcode;

   // Allocate the ODBC environment and save handle.
   retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLAllocHandle(Env) Failed\n\n");
      Cleanup();
      return(9);
   }

   // Notify ODBC that this is an ODBC 3.0 app.
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLSetEnvAttr(ODBC version) Failed\n\n");
      Cleanup();
      return(9);    
   }

   // Allocate ODBC connection handle and connect.
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
      printf("SQLAllocHandle(hdbc1) Failed\n\n");
      Cleanup();
      return(9);
   }

   // This sample use Integrated Security. Please create the SQL Server 
   // DSN by using the Windows NT authentication. 
   retcode = SQLConnect(hdbc1, (UCHAR*)"AdventureWorks", SQL_NTS, (UCHAR*)"",SQL_NTS, (UCHAR*)"", SQL_NTS);
   if ( (retcode != SQL_SUCCESS) &&
      (retcode != SQL_SUCCESS_WITH_INFO) ) {
         ProcessLogMessages(SQL_HANDLE_DBC, hdbc1, "SQLConnect() Failed\n\n", FALSE);
         Cleanup();
         return(9);
   }
   else {
      ProcessLogMessages(SQL_HANDLE_DBC, hdbc1,
         "\nConnect Successful\n\n", FALSE);
   }

   // Allocate statement handle, and then execute command.
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
      ProcessLogMessages(SQL_HANDLE_DBC, hdbc1, "SQLAllocHandle(hstmt1) Failed\n\n", TRUE);
      Cleanup();
      return(9);
   }

   retcode = SQLExecDirect(hstmt1, (UCHAR*)"exec BadOne", SQL_NTS);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
         ProcessLogMessages(SQL_HANDLE_STMT, hstmt1, "SQLExecute() Failed\n\n", TRUE);
         Cleanup();
         return(9);
   }

   // Clear any result sets generated.
   while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA )
      ;

   // Clean up. 
   SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
   SQLDisconnect(hdbc1);
   SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
   SQLFreeHandle(SQL_HANDLE_ENV, henv);
}

void ProcessLogMessages(SQLSMALLINT plm_handle_type, SQLHANDLE plm_handle, char *logstring, int ConnInd) {
   RETCODE plm_retcode = SQL_SUCCESS;
   UCHAR plm_szSqlState[MAXBUFLEN] = "", plm_szErrorMsg[MAXBUFLEN] = "";
   SDWORD plm_pfNativeError = 0L;
   SWORD plm_pcbErrorMsg = 0;
   SQLSMALLINT plm_cRecNmbr = 1;
   SDWORD plm_SS_MsgState = 0, plm_SS_Severity = 0;
   SQLINTEGER plm_Rownumber = 0;
   USHORT plm_SS_Line;
   SQLSMALLINT plm_cbSS_Procname, plm_cbSS_Srvname;
   SQLCHAR plm_SS_Procname[MAXNAME], plm_SS_Srvname[MAXNAME];

   if (logstring)
      printf(logstring);

   while (plm_retcode != SQL_NO_DATA_FOUND) {
      plm_retcode = SQLGetDiagRec(plm_handle_type, plm_handle, plm_cRecNmbr, 
                                  plm_szSqlState, &plm_pfNativeError, plm_szErrorMsg, 
                                  MAXBUFLEN - 1, &plm_pcbErrorMsg);

      // Note that if the application has not yet made a successful connection, 
      // the SQLGetDiagField information has not yet been cached by ODBC Driver Manager and 
      // these calls to SQLGetDiagField will fail.
      if (plm_retcode != SQL_NO_DATA_FOUND) {
         if (ConnInd) { 
            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr,
                                                        SQL_DIAG_ROW_NUMBER, &plm_Rownumber,
                                                        SQL_IS_INTEGER, NULL);

            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr,
                                           SQL_DIAG_SS_LINE, &plm_SS_Line, SQL_IS_INTEGER, NULL);

            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr, 
                                           SQL_DIAG_SS_MSGSTATE, &plm_SS_MsgState,
                                           SQL_IS_INTEGER, NULL);

            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr,
                                           SQL_DIAG_SS_SEVERITY, &plm_SS_Severity,
                                           SQL_IS_INTEGER, NULL);

            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr,
                                           SQL_DIAG_SS_PROCNAME, &plm_SS_Procname,
                                           sizeof(plm_SS_Procname), &plm_cbSS_Procname);

            plm_retcode = SQLGetDiagField( plm_handle_type, plm_handle, plm_cRecNmbr,
                                           SQL_DIAG_SS_SRVNAME, &plm_SS_Srvname, 
                                           sizeof(plm_SS_Srvname), &plm_cbSS_Srvname);
         }

         printf("szSqlState = %s\n", plm_szSqlState);
         printf("pfNativeError = %d\n", plm_pfNativeError);
         printf("szErrorMsg = %s\n", plm_szErrorMsg);
         printf("pcbErrorMsg = %d\n\n", plm_pcbErrorMsg);

         if (ConnInd) {
            printf("ODBCRowNumber = %d\n", plm_Rownumber);
            printf("SSrvrLine = %d\n", plm_Rownumber);
            printf("SSrvrMsgState = %d\n", plm_SS_MsgState);
            printf("SSrvrSeverity = %d\n", plm_SS_Severity);
            printf("SSrvrProcname = %s\n", plm_SS_Procname);
            printf("SSrvrSrvname = %s\n\n", plm_SS_Srvname);
         }
      }

      plm_cRecNmbr++;   // Increment to next diagnostic record.
   }
}

コード

use AdventureWorks
DROP PROCEDURE BadOne
GO

関連項目

その他の技術情報

ODBC の使用法に関するトピック