使用 perl DBI 的 SQL 服务器事务问题
Posted
技术标签:
【中文标题】使用 perl DBI 的 SQL 服务器事务问题【英文标题】:SQL server transaction issue using perl DBI 【发布时间】:2011-07-03 13:26:42 【问题描述】:我在 BEGIN TRAN
和 END TRAN
块中有以下代码块,其中包含 INSERT
和 UPDATE
语句。
现在我们都知道这个操作是原子的。但我不这么看。由于违反唯一约束,插入失败,但仍然发生 UPDATE。当我直接在 SQL Server 中执行相同的部分时,我可以看到该操作是完全原子的。 PERL DBI 前面是否有任何内容覆盖BEGIN TRAN
和COMMIT TRAN
。任何指针?
$dbh->RaiseError = 1; $dbh->PrintError = 1; my $sql = "BEGIN TRAN INSERT INTO $table ... UPDATE $table .... COMMIT TRAN"; $dbh->do($sql);
【问题讨论】:
【参考方案1】:我假设您正在使用 DBD::ODBC,所以当您阅读以下内容时请记住这一点。
默认情况下,DBI 将处于自动提交模式,除非您禁用它。
不要通过 do 方法将使用此类事务的多条 SQL 传递给 SQL Server,因为 DBD::ODBC 默认情况下将使用 SQLExecDirect 执行 do,并且 do 在设计时并没有考虑到多个语句。你最好使用准备/执行或拆分你的 SQL 并像这样在 Perl 中进行提交:
$dbh->RaiseError = 1;
$dbh->begin_work;
eval
$dbh->do(q/insert.../);
$dbh->do(q/update.../);
$dbh->commit;
1;
;
if ($@)
$dbh->rollback or warn "rollback failed";
或将您的插入/更新放在 SQL Server 过程中。
【讨论】:
是的,我们使用 DBD::ODBC - 所以我们可以做一个 $dbh->'AutoCommit' = 0; ?因为我们使用 $dbh->do 从 perl 代码调用了所有查询,并且我们在 BEGIN TRAN 和 COMMIT TRAN 块中拥有所有查询 您可以尝试禁用 AutoCommit,但我不确定它是否能解决整个问题。在do中使用多个sql语句并不是一个好主意。 谢谢 bohica - 除了 DBD::ODBC 之外,我还可以使用任何其他驱动程序,以便我仍然可以拥有 $dbh->do($sql) ,其中 $sql 有 BEGIN TRAN 后跟INSERT/UPDATE 语句后跟 END TRAN。如果它是 DBD::ODBC 的一个已知问题 - 那么任何其他库都可以解决我的问题并使事务仍然是原子的,而不必担心设置 AutoCommit 并每次都进行提交? 嗨 Bohica - 我用 ->begin_work 进行了尝试,效果很好。我也有 $dbh->prepare() 语句,其中有 BEGIN TRAN 后跟 INSERT/UPDATE 语句,然后是 END TRAN。现在,如果我对准备好的块执行 $dbh->execute() ,它将是原子的(即使发生约束违规)还是容易出现 $dbh->do() 之类的问题以上是关于使用 perl DBI 的 SQL 服务器事务问题的主要内容,如果未能解决你的问题,请参考以下文章
如何打印 Perl 的 DBI 填充占位符后执行的 SQL 查询?
如何使用 Perl DBI 检索 DB2 SQL 存储过程的返回值?
Perl DBI / FreeTDS / SQL-Server:如何插入/更新 BLOB varbinary(max) 数据?