FIX: Errors Occur When SQL Server Binary Field Over 64KLast reviewed: September 18, 1997Article ID: Q133311 |
1.52 1.52a 1.52b | 2.00 2.10 2.20
WINDOWS | WINDOWS NTkbprg kbbuglist kbfixlist kbcode The information in this article applies to:
SYMPTOMSWhen you try to store more than 64K of data in a binary field using the SQL Server ODBC 2.0 driver version 2.00.1912, data is truncated. The following error may also occur with the 16-bit version of the driver:
Incorrect syntax near 'NULLNULL'. State:37000[Microsoft][ODBC SQL Server Driver][SQL Server]Note: 32-bit applications using the SQL Server Driver delivered with Visual C++ 4.x (version 2.50.0126) should not exhibit this behavior. CAUSEThe SQL Server driver fails to handle calls to SQLSetParam() correctly. Also, the data needs to be retrieved and sent in chunks less than 64K. The existing implementation for the 32-bit database classes reads and writes the data in one large chunk and encounters network errors with the SQL Server ODBC driver when sending chunks of data larger than 64K.
RESOLUTIONThe SQLSetParam() ODBC 1.0 function has been replaced by the ODBC 2.0 SQLBindParameter() function. The MFC database classes use SQLSetParam to maintain compatibility with ODBC 1.0 drivers. If you are using the SQL Server ODBC 2.0 driver, you can work around the SQLSetParam() bug by calling SQLBindParameter() instead. If you are in a 32-bit environment, you'll also need to override some functions to read and write the binary data in chunks of less than 64K bytes. To fix the MFC Database classes, perform the following steps:
Correction for SendLongBinaryData() CodeBOOL CMyRecordset::Update() { // Insert the CRecordset::Update() code from MFC\SRC\DBCORE.CPP} BOOL CMyRecordset::UpdateInsertDelete() { // Insert the CRecordset::UpdateInsertDelete() code // from MFC\SRC\DBCORE.CPP}
void CMyRecordset::ExecuteUpdateSQL(){ // Insert the CRecordset::ExecuteUpdateSQL() code // from MFC\SRC\DBCORE.CPP}
void CMyRecordset::ExecuteSetPosUpdate(){ // Insert the CRecordset::ExecuteSetPosUpdate() code // from MFC\SRC\DBCORE.CPP}
void CMyRecordset::SendLongBinaryData(HSTMT hstmt){ RETCODE nRetCode; void* pv; AFX_SQL_ASYNC(this, ::SQLParamData(hstmt, &pv)); if (!Check(nRetCode)) { // cache away error CDBException* pException = new CDBException(nRetCode); pException->BuildErrorString(m_pDatabase, hstmt); // then cancel Execute operation Cancel(); THROW(pException); } while (nRetCode == SQL_NEED_DATA) { CLongBinary* pLongBinary = (CLongBinary*)pv; ASSERT_VALID(pLongBinary); const BYTE* lpData = (const BYTE*)::GlobalLock(pLongBinary->m_hData); ASSERT(lpData != NULL); DWORD dwDataLength = 0; while (dwDataLength != pLongBinary->m_dwDataLength) { DWORD dwSend = pLongBinary->m_dwDataLength-dwDataLength; if (dwSend > 0x8000) dwSend = 0x8000; AFX_SQL_ASYNC(this, ::SQLPutData(m_hstmtUpdate, (PTR)lpData, dwSend)); if (!Check(nRetCode)) { ::GlobalUnlock(pLongBinary->m_hData); // Cache away error CDBException* pException = new CDBException(nRetCode); pException->BuildErrorString( m_pDatabase, m_hstmtUpdate); // Then cancel Execute operation Cancel(); THROW(pException); } lpData += dwSend; dwDataLength += dwSend; } // Check for another DATA_AT_EXEC AFX_SQL_ASYNC(this, ::SQLParamData(hstmt, &pv)); if (!Check(nRetCode)) { TRACE0("Error: failure handling long binary" "value during update.\n"); ThrowDBException(nRetCode, hstmt); } }}
STATUSMicrosoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This problem has been corrected in the 32- bit SQL Server driver that ships with Visual C++ 4.0 and 4.1 (driver version 2.50.0126).
REFERENCESFor more information about the ODBC 2.0 SQL Server driver bug (SQLSetParam() not working), please see the following article in the Microsoft Knowledge Base:
ARTICLE-ID: Q125306 TITLE : BUG: Cannot Insert BLOB Data Sized Between 64K and 128K |
Additional reference words: 2.00 2.10 2.20 2.5 2.51 2.52 2.52a 3.0 3.1 3.10
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |