使用 perl DBI 的 SQL 服务器事务问题

Posted

技术标签:

【中文标题】使用 perl DBI 的 SQL 服务器事务问题【英文标题】:SQL server transaction issue using perl DBI 【发布时间】:2011-07-03 13:26:42 【问题描述】:

我在 BEGIN TRAN END TRAN 块中有以下代码块,其中包含 INSERTUPDATE 语句。

现在我们都知道这个操作是原子的。但我不这么看。由于违反唯一约束,插入失败,但仍然发生 UPDATE。当我直接在 SQL Server 中执行相同的部分时,我可以看到该操作是完全原子的。 PERL DBI 前面是否有任何内容覆盖BEGIN TRANCOMMIT 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 填充占位符后执行的 SQL 查询?

Perl DBI - 加载到 SQL Server

如何使用 Perl DBI 检索 DB2 SQL 存储过程的返回值?

Perl 执行 DBI 循环执行

Perl DBI / FreeTDS / SQL-Server:如何插入/更新 BLOB varbinary(max) 数据?