MkUpdtScrRecClause(ScrFields, sTableName, RecArray[i], sSql);
TRY
{
m_pConnPf->ExecuteSQL(sSql);
}
CATCH(CDBException, e)
{
if (AFX_SQL_ERROR_NO_ROWS_AFFECTED == e->m_nRetCode)
{//更新失败,所以插入
MkInsScoreRecClause(ScrFields, sTableName, RecArray[i], sSql);
TRY
{
m_pConnPf->ExecuteSQL(sSql);
}
CATCH(CDBException, e)
{
char szErr[256];
e->GetErrorMessage(szErr, 256);
AfxMessageBox(szErr);
ASSERT(0);
}
END_CATCH
}
else
{
char szErr[256];
e->GetErrorMessage(szErr, 256);
AfxMessageBox(szErr);
ASSERT(0);
}
}
大致思想是,在往一个数据库写入一条记录时,首先对其进行更新,但如果库中不存在这条记录,就要向其插入。在实现上,我认为如果数据库中不存在条件匹配的记录,调用更新操作时,就会返回AFX_SQL_ERROR_NO_ROWS_AFFECTED 异常,捕捉这个异常,然后调用插入语句,就应该可以实现上述功能。
现在的问题是,尽管库中无任何记录,对其进行更新操作仍不抛出异常,因而导致无法插入。请问高手原因何在?或者,要实现上面的功能,更好的办法是什么?在线等待,盼复为谢。
MkUpdtScrRecClause 和 MkInsScoreRecClause是自己写的两个构造SQL语句的函数。
5 个解决方案
#1
要实现上面的功能,更好的办法是什么?
-----------------------------------
没必要使用异常吧
你可以先查询一下(select),如果存在,即可更新
如果不存在,就插入
-----------------------------------
没必要使用异常吧
你可以先查询一下(select),如果存在,即可更新
如果不存在,就插入
#2
用楼上的方法可以很好的实现你的要求。
具体到你的这段代码上,你的m_pConnPf是什么类型的指针?如果是CDatabase类型的,则应该可以的,如果不是,则不能捕捉到异常,因为你的CATCH中只捕捉了CDBException类型的异常。
具体到你的这段代码上,你的m_pConnPf是什么类型的指针?如果是CDatabase类型的,则应该可以的,如果不是,则不能捕捉到异常,因为你的CATCH中只捕捉了CDBException类型的异常。
#3
谢谢二位,我已经用select + IsBOF和IsEof判断查询集是否为空了。但是我还是想知道为何没有异常抛出,m_pConnPf是一个CDataBase类指针。
这里不用select语句的原因,是因为更新和插入记录,可以直接用m_pConnPf对象完成,用CRecordset对象(需要临时构造和生成记录集)会慢一些。
这里不用select语句的原因,是因为更新和插入记录,可以直接用m_pConnPf对象完成,用CRecordset对象(需要临时构造和生成记录集)会慢一些。
#4
你捕获所有的异常类型看看,是不是异常没有捕获到呢?或者我想可能就是返回了一个错误?
我在ado中也没有抛出, 可能是这样的, 你的更新语句被dbms执行时首先进行了查找的, 结果是返回记录集为空集,所以会返回SQLSTATE=02000,只是一个warning,看来还是得用select查找一下先
我在ado中也没有抛出, 可能是这样的, 你的更新语句被dbms执行时首先进行了查找的, 结果是返回记录集为空集,所以会返回SQLSTATE=02000,只是一个warning,看来还是得用select查找一下先
#5
要不试试下面的、方法:
try
{
}
catch (_com_error e)
{
CString strMsg;
strMsg.Format(_T("Error: %081x \nErrorMessage: %s \nSource: %s \nDescription: %s\n"),\e.Error(), e.ErrorMessage(), (LPCTSTR)_bstr_t(e.Source()),\
(LPCTSTR)_bstr_t(e.Description()));
MessageBox(strMsg, _T("失败!"), MB_OK|MB_ICONWARNING);
}
try
{
}
catch (_com_error e)
{
CString strMsg;
strMsg.Format(_T("Error: %081x \nErrorMessage: %s \nSource: %s \nDescription: %s\n"),\e.Error(), e.ErrorMessage(), (LPCTSTR)_bstr_t(e.Source()),\
(LPCTSTR)_bstr_t(e.Description()));
MessageBox(strMsg, _T("失败!"), MB_OK|MB_ICONWARNING);
}
#1
要实现上面的功能,更好的办法是什么?
-----------------------------------
没必要使用异常吧
你可以先查询一下(select),如果存在,即可更新
如果不存在,就插入
-----------------------------------
没必要使用异常吧
你可以先查询一下(select),如果存在,即可更新
如果不存在,就插入
#2
用楼上的方法可以很好的实现你的要求。
具体到你的这段代码上,你的m_pConnPf是什么类型的指针?如果是CDatabase类型的,则应该可以的,如果不是,则不能捕捉到异常,因为你的CATCH中只捕捉了CDBException类型的异常。
具体到你的这段代码上,你的m_pConnPf是什么类型的指针?如果是CDatabase类型的,则应该可以的,如果不是,则不能捕捉到异常,因为你的CATCH中只捕捉了CDBException类型的异常。
#3
谢谢二位,我已经用select + IsBOF和IsEof判断查询集是否为空了。但是我还是想知道为何没有异常抛出,m_pConnPf是一个CDataBase类指针。
这里不用select语句的原因,是因为更新和插入记录,可以直接用m_pConnPf对象完成,用CRecordset对象(需要临时构造和生成记录集)会慢一些。
这里不用select语句的原因,是因为更新和插入记录,可以直接用m_pConnPf对象完成,用CRecordset对象(需要临时构造和生成记录集)会慢一些。
#4
你捕获所有的异常类型看看,是不是异常没有捕获到呢?或者我想可能就是返回了一个错误?
我在ado中也没有抛出, 可能是这样的, 你的更新语句被dbms执行时首先进行了查找的, 结果是返回记录集为空集,所以会返回SQLSTATE=02000,只是一个warning,看来还是得用select查找一下先
我在ado中也没有抛出, 可能是这样的, 你的更新语句被dbms执行时首先进行了查找的, 结果是返回记录集为空集,所以会返回SQLSTATE=02000,只是一个warning,看来还是得用select查找一下先
#5
要不试试下面的、方法:
try
{
}
catch (_com_error e)
{
CString strMsg;
strMsg.Format(_T("Error: %081x \nErrorMessage: %s \nSource: %s \nDescription: %s\n"),\e.Error(), e.ErrorMessage(), (LPCTSTR)_bstr_t(e.Source()),\
(LPCTSTR)_bstr_t(e.Description()));
MessageBox(strMsg, _T("失败!"), MB_OK|MB_ICONWARNING);
}
try
{
}
catch (_com_error e)
{
CString strMsg;
strMsg.Format(_T("Error: %081x \nErrorMessage: %s \nSource: %s \nDescription: %s\n"),\e.Error(), e.ErrorMessage(), (LPCTSTR)_bstr_t(e.Source()),\
(LPCTSTR)_bstr_t(e.Description()));
MessageBox(strMsg, _T("失败!"), MB_OK|MB_ICONWARNING);
}