困惱了一個星期的問題終於解決了。之前,在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中具體爲:
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)啊。