MS SQL SERVER 2008. Qt + ODBC。
我正在尝试通过回滚最高级别的事务来回滚数据库中的一些更改(在内部进行)。但看起来我的第二个db.transaction()调用没有增加@@ TRANCOUNT和第一个提交(内部)关闭事务completly。因此,外部事务级别中的下一个rollback命令才会被忽略。
一些例子。每次操作后,已注释的字符串显示从DB收到的@@ TRANCOUNT:
db.transaction(); //@@TRANCOUNT = 0
query->exec("INSERT INTO TestOnly (Value) VALUES('1')");//@@TRANCOUNT = 1
db.transaction(); //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('2')");//@@TRANCOUNT = 1
db.commit(); //@@TRANCOUNT = 0
query->exec("INSERT INTO TestOnly (Value) VALUES('3')");//@@TRANCOUNT = 0
db.rollback(); //@@TRANCOUNT = 0
测试代码:
...
db = QSqlDatabase::addDatabase("QODBC3");
...
query = new QSqlQuery(db);
...
bool ok;
ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //0
query->exec("INSERT INTO TestOnly (Value) VALUES('1')");
PrintTranCount(); //1
ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //2
query->exec("INSERT INTO TestOnly (Value) VALUES('2')");
PrintTranCount(); //3
ok = db.commit(); qDebug() << "Commit transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //4
query->exec("INSERT INTO TestOnly (Value) VALUES('3')");
PrintTranCount(); //5
ok = db.rollback(); qDebug() << "Rollback transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //6
调试输出:
Start transaction result = true ; errorText: " "
Transaction Count 0: 0
Transaction Count 1: 1
Start transaction result = true ; errorText: " "
Transaction Count 2: 1
Transaction Count 3: 1
Commit transaction result = true ; errorText: " "
Transaction Count 4: 0
Transaction Count 5: 0
Rollback transaction result = true ; errorText: " "
Transaction Count 6: 0
PrintTranCount()函数:
static int Num = 0;
query->exec("SELECT @@TRANCOUNT");query->first();
qDebug() << "Transaction Count "<< Num << ": " <<query->value(0).toInt();
Num++;
第二次交易后,交易柜台(@@ TRANCOUNT)没有增加到2的原因是什么?我没有正确理解交易柜台的想法?或者数据库/驱动程序设置有问题?也许我错过了我的示例代码中的一些错误?
我会感激任何提示。对不起谷歌翻译:)
答案 0 :(得分:0)
通过查看源代码解决了所有问题:
db.transaction()不会向数据库发送任何“begin tran”命令(至少使用ODBC驱动程序)。此功能仅将提交模式更改为“manual commit mode”。之后,首先db.commit()确认所有更改(通过发送“SQLEndTran”命令)并再次将模式更改回“自动提交模式”。
要使用@@ TRANCOUNT的“嵌套”(非真正嵌套)事务,只需手动将“tran begin”/“commit”/“rollback”命令发送到数据库即可。在我的例子中:
query->exec("begin tran"); //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('1')");//@@TRANCOUNT = 1
query->exec("begin tran"); //@@TRANCOUNT = 2
query->exec("INSERT INTO TestOnly (Value) VALUES('2')");//@@TRANCOUNT = 2
query->exec("commit"); //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('3')");//@@TRANCOUNT = 1
query->exec("rollback"); //@@TRANCOUNT = 0