文章編號: 259691 - 上次校閱: 2005年10月12日 - 版次: 4.4

FIX: 錯誤訊息 「 無效的時間格式 」 當您插入日期/時間與最大值

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

徵狀

當您使用 Microsoft SQL Server ODBC 驅動程式,而且您使用 SQLSetPos 來插入或為小時、 分鐘、 秒及毫秒部分 (如 「 1999年-10-03 23:59:59:999) 包含最大允許值的更新日期或時間值,插入陳述式會成功,但不正確的值儲存到資料庫。

如果您嘗試重新選取日期/時間值返回,陳述式會產生錯誤或傳回不正確的值取決於 [日期/時間] 欄位所繫結。如果 [] 欄位結合成一個 SQL_C_TIMESTAMP,就會發生錯誤訊息下列敘述所示:
SQLState = 22007
[Microsoft][ODBC SQL Server ODBC 驅動程式]時間格式不正確
欄位繫結為一個 SQL_C_CHAR 時, 不會發生錯誤 ; 然而,不正確的值會傳回,1999年-10-03 24:00:00.000 等。這可以接收的應用程式中產生錯誤,因為 24:00:00.000 不是有效的日期/時間值。

與 Windows 2000/MDAC 2.5 組建的 SQL Server ODBC 驅動程式 (版本 3.70.820) 或更早版本,就會發生這個錯誤。

發生的原因

將轉換日期/時間的演算法中的錯誤不將透過時間的小時部分循環日期天的部分。

解決方案

支援的 Hotfix 現在可以從 Microsoft,但它只用來修正本文所述的問題。僅適用於發生此特定問題的系統。此 Hotfix 可能會接受其他測試。因此,如果您不會嚴重影響這個問題,我們建議您等候下一個的 Microsoft 資料存取元件 Service Pack 包含此 Hotfix。

如果要立即解決這個問題,洽詢 Microsoft 技術支援部以取得此修正程式。如需 Microsoft 產品支援服務電話號碼及支援成本的相關資訊的完整清單,請造訪下列 Microsoft 網站]:
http://support.microsoft.com/contactus/?ws=support (http://support.microsoft.com/contactus/?ws=support)
注意: 在特殊情況中通常會因支援電話所產生的費用如果,可能就不收取 Microsoft 支援人員認為某特定更新程式可以解決您的問題。典型的支援成本將會套用到其他支援問題是所做不限定特定有問題的更新程式。



此修正程式的英文版應該具有下列檔案屬性或更新版本:

   Date       Version      Size             File name    
   -----------------------------------------------------

   04/04/00   3.70.0784     24,848 bytes    Odbcbcp.dll
   04/04/00   3.70.0784    516,368 bytes    Sqlsrv32.dll

				




因應措施

以下是這個問題的兩種潛在的解決方法:
  • 如果可以執行插入並更新透過直接讓 SQL Server 的 SQL 陳述處理日期/時間值的轉換。

    -或者-

  • 如果不需要的毫秒儲存,請將欄位定義為 smalldatetime 資料型別,而非日期時間。smalldatetime 資料型別只儲存體,使用 4 個位元組,而且也未納入毫秒精確度。

狀況說明

Microsoft 已確認這是在本文開頭所列之 Microsoft 產品中的有錯誤。

其他相關資訊

手動安裝的 Hotfix 檔案

  1. 請結束任何應用程式或使用 SQL Server ODBC 驅動程式 Sqlsrv32.dll 的服務。這可能包含網際網路資訊伺服器 」 (IIS)、 Microsoft 交易伺服器 (MTS) 及任何 ODBC、 Microsoft ActiveX 資料物件 (ADO) 或 OLE DB 應用程式。
  2. 下載 Hotfix 到暫存目錄。
  3. 找出並重新命名 Sqlsrv32.dll 和 Odbcbcp.dll 檔案,應該是在執行 Microsoft Windows NT 的電腦 \Winnt\System32 資料夾中,執行 Microsoft Windows 95 與 Microsoft Windows 98 的電腦 \Windows\System 資料夾中的目前版本。
  4. 將 Hotfix 檔案複製到相同的位置,然後重新啟動您的服務及應用程式。

重製行為的步驟

  1. 在步驟 2 到 Microsoft Visual C++ 主控台應用程式中複製程式碼,並編譯程式碼。請注意您可能需要變更資料來源名稱、 使用者 ID 和密碼。
  2. 執行程式碼,並注意繫結 SQL_C_TIMESTAMP,作為日期/時間值時,會發生錯誤,而且是無效的小時值會傳回繫結 SQL_C_CHAR 為日期/時間值時
    #include <windows.h>
    #include <stdio.h>
    #include <sql.h>
    #include <sqlext.h>
    #include <time.h>
    
    void CreateTable(HSTMT);
    
    main()
    {
    
    //	ODBC handles
    	RETCODE rc;
    	HENV henv;
    	HDBC hdbc;
    	HSTMT hstmt;
    
    //	Variables for SQLConnect
    
    	char * dsn = "Pubs";
    	char * uid = "sa";
    	char * pwd = "";
    
    //	Variables for SQLDiagRec
    	char mstate[6] = "\0";
    	long native = 0;
    	char mtext[300] = "\0";
    	short mlength = 0;
    	short i = 0;
    	
    //	Variables for SQLBindCol
    	int m_ID = 1;
    	long m_idLen = 4;
    	TIMESTAMP_STRUCT m_time = {1999,10,03,23,59,59,999000000};
    	char m_timeChar[30] = "\0";
    	long m_timeLen = 16;
    	long sqlnts = SQL_NTS;
    
    //	miscellaneous variables	
    	char * strSQL = "Select * from MillisecTest";
    	char * strDropTable = "Drop table MillisecTest";
    	unsigned short status = 0;
    	unsigned long rowcount = 0;
    
    
    
    //	Allocate ODBC handles and connect
    	rc = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
    	rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3,0);
    	rc = SQLAllocHandle(SQL_HANDLE_DBC,henv, &hdbc);
    
    	rc = SQLConnect(hdbc, (unsigned char *)dsn,
    		SQL_NTS, (unsigned char *)uid,
    		SQL_NTS, (unsigned char *)pwd, SQL_NTS);
    
    	rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    
    //	Table creation 
    	CreateTable(hstmt);
    
    //	Set statement attributes so SQLSetPos can be used
    	rc = SQLSetStmtAttr( hstmt, SQL_ATTR_CONCURRENCY, (SQLPOINTER)SQL_CONCUR_LOCK, 0 );
    	rc = SQLSetStmtAttr( hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0 );
    
    //	Bind the columns, using SQL_C_TIMESTAMP
    	rc = SQLBindCol(hstmt, 1, SQL_C_SHORT, &m_ID, 4, &m_idLen);
    	rc = SQLBindCol(hstmt, 2, SQL_C_TIMESTAMP, &m_time, sizeof(m_time), &m_timeLen);
    
    //	Execute the statement and use SQLSetPos to insert the date/time data
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    	rc = SQLSetPos(hstmt, 1, SQL_ADD, SQL_LOCK_NO_CHANGE);
    
    
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    	memset(&m_time, 0, sizeof(m_time));
    
    //	Re-execute the statement, and attempt to fetch back the new date/time value
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    
    	SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, 1, (unsigned char *)&mstate, &native, 
    				(unsigned char *)&mtext, 300, &mlength);
    	printf("\nError when attempting to bind as SQL_C_TIMESTAMP:\n\n");
    	printf("\tSQLSTATE\t%s\n\tNative Error\t%i\n\tMessage\t%s\n\n",mstate, native, mtext);
    
    
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    //	Bind the date/time column as SQL_C_CHAR this time
    	rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, m_timeChar, sizeof(m_timeChar), &sqlnts);
    	rc = SQLExecDirect(hstmt, (unsigned char *)strSQL, SQL_NTS);
    	rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 1, &rowcount, &status );
    	printf("\nInvalid hour when timestamp is bound as SQL_C_CHAR:  %s\n\n", m_timeChar); 
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	
    
    
    //	Cleanup
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	SQLExecDirect(hstmt, (unsigned char *)strDropTable, SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	SQLFreeStmt(hstmt, SQL_DROP);
    	SQLDisconnect(hdbc);
    	SQLFreeConnect(hdbc);
    	SQLFreeEnv(henv);
    
    	printf("\nDo the \"Press any key\" thing...");
    	getchar();
    	return(TRUE);
    };
    
    //------- CreateTable() ----------------
    
    void CreateTable(HSTMT hstmt)
    {
    
    	RETCODE rc = 0;
    	char SqlStatements[2][90] = 
    	{"Drop table MillisecTest",
    	"Create table MillisecTest (ID integer constraint index1 PRIMARY KEY, TimeTest datetime)"};
    
    	rc = SQLExecDirect(hstmt, (unsigned char *)SqlStatements[0], SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    	rc = SQLExecDirect(hstmt, (unsigned char *)SqlStatements[1], SQL_NTS);
    	SQLFreeStmt(hstmt, SQL_CLOSE);
    
    
    }
    					

這篇文章中的資訊適用於:
  • Microsoft Data Access Components 2.1 Service Pack 2
  • Microsoft Data Access Components 2.1 Service Pack 1
  • Microsoft Data Access Components 2.1 Service Pack 2
  • Microsoft Data Access Components 2.5
  • Microsoft ODBC Driver for Microsoft SQL Server 3.7
關鍵字:?
kbmt kbhotfixserver kbqfe kbbug kbcodesnippet kbdatabase kbfix kbmdac210sp2fix kbqfe KB259691 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:259691? (http://support.microsoft.com/kb/259691/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。