CDatabase::executeSql 之vc 6.0 與 vs 2008 的區別

困惱了一個星期的問題終於解決了。之前,在vs 2008 上用 CDatabase::executeSql("update bp_tmpbatch_tb set progress_flag = 0 where
1 = 0 ")的語句,總是莫名奇妙的拋出異常,"錯誤的函數序列"。一開始觀察執行的sql語句 ,發現sql語句在語法上並沒有錯,對比在vc 6.0環境
執行的情況,並沒有報錯,很難理解,於是認爲 vs2008上  CDatabase::executeSql()執行updata,delete 都會報錯,然後各種百度,各種go
ogle,都找不到答案,各種鬱悶。
      今天,經過各種失敗後,終於轉變思維,發現"update bp_tmpbatch_tb set progress_flag = 0 where 1 = 0 " 這句話 在sql語句上沒問題,
但它卻沒有結果集,所以 vs2008上  CDatabase::executeSql()拋異常了,接着測試了其他另外幾條類似的語句,得到相同的異常,但當 CD
atabase::executeSql()執行 "update bp_tmpbatch_tb set progress_flag = 0 where batch_id =  '20110331094619171022' "這種有結果集的
語句時,是不會拋異常的。
       同一條語句,在vc 6.0 與 vs 2008執行有差別,主要在與vc 6.0 的CDatabase::executeSql()和 vs 2008的CDatabase::executeSql()
實現方式不一樣,vc 6.0中具體爲:

所以,要解決VS2008無記錄集不報錯,還得自己派生CDatabase,然後重寫 void CDatabase::ExecuteSQL(LPCTSTR lpszSQL)啊。

 

 
void CDatabase::ExecuteSQL(LPCTSTR lpszSQL)
{
USES_CONVERSION;
RETCODE nRetCode;
HSTMT hstmt;
ASSERT_VALID(this);
ASSERT(AfxIsValidString(lpszSQL));

AFX_SQL_SYNC(::SQLAllocStmt(m_hdbc, &hstmt));
if (!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);


TRY
{
OnSetOptions(hstmt);

// Give derived CDatabase classes option to use parameters
BindParameters(hstmt);

AFX_ODBC_CALL(::SQLExecDirect(hstmt,
(UCHAR*)T2A((LPTSTR)lpszSQL), SQL_NTS));


if (!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);
else
{
do
{
SWORD nResultColumns;
AFX_ODBC_CALL(::SQLNumResultCols(hstmt, &nResultColumns));
if (nResultColumns != 0)
{
do
{
AFX_ODBC_CALL(::SQLFetch(hstmt));
} while (CheckHstmt(nRetCode, hstmt) &&
nRetCode != SQL_NO_DATA_FOUND);
}
AFX_ODBC_CALL(::SQLMoreResults(hstmt));
} while (CheckHstmt(nRetCode, hstmt) &&
nRetCode != SQL_NO_DATA_FOUND);
}
}
CATCH_ALL(e)
{
::SQLCancel(hstmt);
AFX_SQL_SYNC(::SQLFreeStmt(hstmt, SQL_DROP));
THROW_LAST();
}
END_CATCH_ALL


AFX_SQL_SYNC(::SQLFreeStmt(hstmt, SQL_DROP));
}

vs 2008 爲:

void CDatabase::ExecuteSQL(LPCTSTR lpszSQL)
{
RETCODE nRetCode;
HSTMT hstmt;


ENSURE_VALID(this);
ENSURE_ARG(AfxIsValidString(lpszSQL));


AFX_SQL_SYNC(::SQLAllocStmt(m_hdbc, &hstmt));
if (!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);


TRY
{
OnSetOptions(hstmt);
// Give derived CDatabase classes option to use parameters
BindParameters(hstmt);
LPTSTR pszSQL = const_cast<LPTSTR>(lpszSQL);
AFX_ODBC_CALL(::SQLExecDirect(hstmt, reinterpret_cast<SQLTCHAR *>(pszSQL), SQL_NTS));
if (!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);

SWORD nResultColumns;
do
{
AFX_ODBC_CALL(::SQLNumResultCols(hstmt, &nResultColumns));
if(!CheckHstmt(nRetCode, hstmt))  //  vs 2008 這裏多出一些判斷,更加嚴謹了,無記錄集會拋異常。
AfxThrowDBException(nRetCode, this, hstmt);
if (nResultColumns != 0)
do
{
AFX_ODBC_CALL(::SQLFetch(hstmt));
if(!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);
} while (nRetCode != SQL_NO_DATA_FOUND);
AFX_ODBC_CALL(::SQLMoreResults(hstmt));
if(!CheckHstmt(nRetCode, hstmt))
AfxThrowDBException(nRetCode, this, hstmt);
} while (nRetCode != SQL_NO_DATA_FOUND);
}
CATCH_ALL(e)
{
::SQLCancel(hstmt);
AFX_SQL_SYNC(::SQLFreeStmt(hstmt, SQL_DROP));
THROW_LAST();
}
END_CATCH_ALL


AFX_SQL_SYNC(::SQLFreeStmt(hstmt, SQL_DROP));
}

所以,要解決VS2008無記錄集不報錯,還得自己派生CDatabase,然後重寫 void CDatabase::ExecuteSQL(LPCTSTR lpszSQL)啊。

發佈了19 篇原創文章 · 獲贊 16 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章