困恼了一个星期的问题终于解决了。之前,在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)啊。