狀況
當您嘗試設定 ODBC 連線的連線屬性,會啟用連接共用藉由使用 ODBC 驅動程式 API,Microsoft SQL Server ODBC 驅動程式時,您會收到下列錯誤訊息︰
IM006 [Microsoft] [ODBC 驅動程式管理員] 驅動程式 SQLSetConnectAttr 失敗
注意ODBC 驅動程式文件提及的訊息是資訊訊息。不過,您會收到的訊息當做錯誤訊息。
當下列所有情況皆成立時,可能會發生這個問題︰-
您可以使用 SQLConnect 的 ODBC 驅動程式 API,以進行與資料來源名稱 (DSN) 的連線。
-
其中一個預設屬性的資料來源名稱 (例如使用 ANSI null、 paddings 和警告選項中) 已停用。
-
環境控制代碼會啟用連接共用。
-
您使用 SQLConnect 來開啟連接後,將設定連線的交易隔離層級屬性。
-
執行資料庫交易。
因應措施
若要解決這個問題,請依照下列步驟執行:
-
停用連接共用 ODBC 連線的選項。
注意停用連接共用,可能會影響應用程式的效能。 -
您認可該交易之後,不開啟自動認可選項。
-
開啟 [ODBC 連線前,請設定交易隔離等級。
-
使用 dsn 的連接,而不是取得 ODBC 連線以 DSN。
解決方案
支援的 hotfix 可從 Microsoft 取得。不過,此 Hotfix 僅用於修正本文中所述的問題。此 Hotfix 只適用於發生此特定問題的系統上。
如果 hotfix 可供下載,在此知識庫文件頂端將出現「可用的 Hotfix」區段。如果這個區段不會出現,將要求提交給 Microsoft 客戶服務及支援取得 Hotfix。 注意如果發生其他問題,或如果需要進行疑難排解,您可能必須建立個別的服務要求。收取支援費用會套用到其他支援問題和此特定 hotfix 無法解決的問題。如 Microsoft 客戶服務及支援的電話號碼或建立個別的服務要求的完整清單,請造訪下列 Microsoft 網站︰http://support.microsoft.com/contactus/?ws=support注意「 下載 Hotfix 」 表單會顯示 hotfix 可用的語言。如果看不到您的語言,是因為未提供該語言的 Hotfix 。此修正程式的英文版具有的檔案屬性 (或更新) 下表中所列。國際標準時間 (UTC) 中,所列的日期和時間,這些檔案。當您檢視檔案資訊時,會將它轉換為本地時間。若要查看 UTC 與當地時間的時差,請使用 在 [控制台] 中的 [日期和時間] 工具中的 [時區] 索引標籤。 MDAC 2.7 SP1 Date Time Version Size File name -------------------------------------------------------- 13-Oct-2002 19:24 90,112 Dahotfix.exe 03-Jul-2003 04:09 2000.81.9031.51 372,736 Sqlsrv32.dll MDAC 2.8 Date Time Version Size File name -------------------------------------------------------- 31-Mar-2004 16:44 2000.85.1040.0 24,576 Odbcbcp.dll 31-Mar-2004 16:43 2000.85.1040.0 401,408 Sqlsrv32.dll
注意如需所有可用的 MDAC 2.8 的 hotfix 清單,按一下下面的文件編號,檢視 「 Microsoft 知識庫 」 中的文件︰
839801修正︰ Hotfix 可供 MDAC 2.8
狀態
Microsoft 已確認這是在 < 適用於=""> 一節所列出的 Microsoft 產品的問題。這個問題已經獲得修正在 Microsoft 資料存取元件 2.7 Service Pack 1 重新整理和 Microsoft 資料存取元件 2.8。
更多的資訊
您會看到只當您有 Microsoft 資料存取元件 (MDAC) 2.7 Service Pack 1 安裝在電腦上,會將在本文 < 徵狀=""> 一節中提到的問題。
重現問題的步驟
重現問題,請使用下列程式碼︰
// ODBCTestCase.cpp : Defines the entry point for the console application.
// #include "stdafx.h" #include "windows.h" #include "sqlext.h" #include "sql.h" #include "stdlib.h" void GetSQLError(); long InitializeEnvironment(); long Connect(BOOL lbUseDSN); long Disconnect(); int ExecuteProcedure(); SQLHENV ghEnvironment = NULL; SQLHDBC ghConnection = NULL; HSTMT ghStatement = NULL; /********************************************** * main **********************************************/ int main(int argc, char* argv[]) { BOOL lbTransaction = TRUE; BOOL lbUseDSN = FALSE; long lValue =0; if(argc > 1) { if(strcmp(argv[1], "DSN") == 0) lbUseDSN = TRUE; if(argc > 2) { if(strcmp(argv[2], "TRAN") == 0) lbTransaction = TRUE; } } if(InitializeEnvironment() == 0) { for(long llSub = 0; llSub < 2; llSub++) { if(Connect(lbUseDSN) == 0) { if(lbTransaction) SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF); //SQLGetConnectAttr(ghConnection,SQL_ATTR_AUTOCOMMIT,&lValue,0,NULL); ExecuteProcedure(); if(lbTransaction) { SQLTransact(ghEnvironment, ghConnection, SQL_COMMIT); //If you do not call the following, the problem does not occur: SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_ON); //If you call the following the problem does not occur: //SQLSetConnectOption(ghConnection, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF); //SQLGetConnectAttr(ghConnection,SQL_ATTR_AUTOCOMMIT,&lValue,0,NULL); } Disconnect(); } } SQLFreeHandle(SQL_HANDLE_ENV, ghEnvironment); } return 0; } /********************************************** * InitializeEnvironment **********************************************/ long InitializeEnvironment() { if (!SQL_SUCCEEDED(SQLSetEnvAttr(NULL, SQL_ATTR_CONNECTION_POOLING, (SQLPOINTER)SQL_CP_ONE_PER_DRIVER, SQL_IS_INTEGER))) { GetSQLError(); return 8; } if(!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, NULL, &ghEnvironment))) { GetSQLError(); return 8; } if(!SQL_SUCCEEDED(SQLSetEnvAttr(ghEnvironment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC2, SQL_IS_INTEGER))) { GetSQLError(); return 8; } if (!SQL_SUCCEEDED(SQLSetEnvAttr(ghEnvironment, SQL_ATTR_CP_MATCH, (SQLPOINTER) SQL_CP_STRICT_MATCH , //(SQLPOINTER) SQL_CP_RELAXED_MATCH , SQL_IS_INTEGER))) { GetSQLError(); return 8; } return 0; } /********************************************** * Connect **********************************************/ long Connect(BOOL lbUseDSN) { SQLCHAR lszOutConnectString[1024]; SQLSMALLINT llReturnLength; SQLAllocHandle(SQL_HANDLE_DBC, ghEnvironment, &ghConnection); // If you set the isolation before opening the connection, no error reported. // Customer cannot set this attribute before opening connection because the object //is running under COM+, and under COM+ isolation levels automatically are set to serializable //if(!SQL_SUCCEEDED(::SQLSetConnectAttr(ghConnection, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)SQL_TXN_READ_COMMITTED , SQL_IS_INTEGER))) //{ // GetSQLError(); // return 8; //} if(lbUseDSN) { int iReturn = ::SQLConnect(ghConnection, (SQLCHAR*)"LocalCPR", SQL_NTS, (SQLCHAR*)"sa", SQL_NTS, (SQLCHAR*)"password1", SQL_NTS); if(!SQL_SUCCEEDED(iReturn)) { GetSQLError(); return 8; } } else { if(!SQL_SUCCEEDED(SQLDriverConnect(ghConnection, NULL, (SQLCHAR*)"DSN=LocalCPR;UID=sa;PWD=password1;", SQL_NTS, lszOutConnectString, 1024, &llReturnLength, SQL_DRIVER_NOPROMPT))) { GetSQLError(); return 8; } } SQLAllocStmt(ghConnection, &ghStatement); //If you set the isolation after you open the connection, you see the problem. if(!SQL_SUCCEEDED(::SQLSetConnectAttr(ghConnection, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)SQL_TXN_READ_COMMITTED , SQL_IS_INTEGER))) { GetSQLError(); return 8; } return 0; } /********************************************** * Disconnect **********************************************/ long Disconnect() { if(ghStatement) { if(!SQL_SUCCEEDED(SQLFreeHandle(SQL_HANDLE_STMT, ghStatement))) { GetSQLError(); return 8; } ghStatement = NULL; } if(ghConnection) { ::SQLDisconnect(ghConnection); if(!SQL_SUCCEEDED(SQLFreeHandle(SQL_HANDLE_DBC, ghConnection))) { GetSQLError(); return 8; } ghConnection = NULL; } return 0; } /********************************************** * ExecuteProcedure **********************************************/ int ExecuteProcedure() { SQLINTEGER mlIndicator = 0; SQLRETURN lnSqlRetCd = SQL_SUCCESS; ::SQLFreeStmt(ghStatement, SQL_CLOSE); ::SQLFreeStmt(ghStatement, SQL_UNBIND); /*****************************************************************/ /* Execute Procedure /*****************************************************************/ RETCODE llDbRetCd = SQLExecDirect(ghStatement, (SQLCHAR*)"SELECT * From Table1", SQL_NTS); if((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO)) { GetSQLError(); return 8; } /*****************************************************************/ /* Bind return Value /*****************************************************************/ char lszReturnBuf[300]; SDWORD lSts; llDbRetCd = SQLBindCol(ghStatement, 1, SQL_C_TCHAR, &lszReturnBuf, 300, &lSts); if ((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO)) { GetSQLError(); return 8; } /*****************************************************************/ /* Fetch Result /*****************************************************************/ llDbRetCd = SQLFetch(ghStatement); if ((llDbRetCd != SQL_SUCCESS) && (llDbRetCd != SQL_SUCCESS_WITH_INFO)) { GetSQLError(); return 8; } printf("Output Value : %s\n",lszReturnBuf); return 0; } /********************************************** * GetSQLError **********************************************/ void GetSQLError() { long llDbErrCd = 0; short llRetMsgLen = 0; char lszSqlErrMsg[255]; char lszSqlMsg[255]; SQLError(ghEnvironment, ghConnection, ghStatement, (SQLCHAR*) lszSqlErrMsg, &llDbErrCd, (SQLCHAR*) lszSqlMsg, 255, &llRetMsgLen); printf(lszSqlErrMsg); printf(lszSqlMsg); }