发现ACCESS的BUG
先创建一个表,
然后启用事务,
接着删除一个不存在的记录,
再删除表,
最后结束事务,
运行时在删除表时出错,
ADO的报错信息是:
由于表 'ssss' 正被别的用户或进程使用,数据库引擎无法锁定它。
以上代码在使用Oracle时顺利运行通过,
唯独ACCESS不行,
如果去掉事务的代码就没问题,
如果只去掉删除记录的代码也没问题,
如果把删除记录的代码更换成检索记录也没问题,
但事务和删除记录的代码同时存在就有问题,
我是在VS2008上使用ADO,
Microsoft.Jet.OLEDB.4.0和Microsoft.ACE.OLEDB.12.0都试过,
都有这个问题,
怎么看都像是ACCESS的BUG。
代码如下:
#include <locale.h>
#include <atlstr.h>
#include <atlcom.h>
#import "c:\Program Files\Common Files\System\ado\msado15.dll" rename_namespace("ADO_ns") rename("EOF","ADO_EOF")
#import "c:\Program Files\Common Files\system\ado\msadox.dll" rename_namespace("ADO_EX_ns")
void Init(ADO_ns::_ConnectionPtr& clConnection)
{
if (FAILED(clConnection.CreateInstance(__uuidof(ADO_ns::Connection))))
{
throw 0;
}
try
{
ADO_EX_ns::_CatalogPtr clLocal = NULL;
if (FAILED(clLocal.CreateInstance((__uuidof(ADO_EX_ns::Catalog)))))
{
throw 0;
}
clLocal->Create(_bstr_t(_T("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=e:\\AAAA.accdb;")));
clConnection->Open(_bstr_t(_T("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=e:\\AAAA.accdb;")), _bstr_t(), _bstr_t(), ADO_ns::adModeUnknown);
}
catch (const _com_error& clErr)
{
wprintf(LPCTSTR(clErr.Description()));
throw 0;
}
}
void Execute(ADO_ns::_ConnectionPtr& clConnection, const CString& clSQL)
{
_variant_t clRecordsAffected;
try
{
clConnection->Execute(_bstr_t(clSQL), &clRecordsAffected, ADO_ns::adCmdText | ADO_ns::adExecuteNoRecords);
}
catch (const _com_error& clErr)
{
wprintf(LPCTSTR(clErr.Description()));
throw 0;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "chs");
CoInitialize(NULL);
ADO_ns::_ConnectionPtr clConnection;
Init(clConnection);
Execute(clConnection, _T("create table ssss(ss integer)"));
clConnection->BeginTrans();
Execute(clConnection, _T("delete from ssss where ss=11"));
Execute(clConnection, _T("drop table ssss"));
clConnection->CommitTrans();
clConnection.Release();
CoUninitialize();
return 0;
}
------解决方案--------------------
应该不是BUG,各个数据库对同一个标准的解释和理解不同。
delete from table1 where id<0
drop table table1;
打开事务后,理论上,DDL语句应该自动提交一个commit; 但ACCESS中显然先做了检查。
------解决方案--------------------
在ACCESS中用VBA测试:
CurrentProject.Connection.Execute "begin TRANSACTION"
CurrentProject.Connection.Execute "create table try1(id int,bh varchar(10))"
CurrentProject.Connection.Execute "create table try2(id int,bh varchar(10))"
CurrentProject.Connection.Execute "insert into try1 values(1,'2')"
CurrentProject.Connection.Execute "delete from try1 where id=5"
CurrentProject.Connection.Execute "drop table try1"
CurrentProject.Connection.Execute "COMMIT TRANSACTION"
没有问题啊,DDL可以回滚