【问题标题】:Perl DBI - Getting records affected of each statement in a transactionPerl DBI - 获取事务中每个语句影响的记录
【发布时间】:2011-05-11 06:31:56
【问题描述】:

嗨,

我使用 perl DBI do(),它将执行下面的 SQL 块,如下所示,在 SQL SERVER 2005 中执行

    eval {
            my $result =  do(<<SQL);
            BEGIN TRAN

            UPDATE table1 SET
            col1 = 999 where date = '2010-08-27'

            DELETE FROM table1
            where date = '2010-08-30'

            COMMIT TRAN
SQL
    $logger->info($result);
};

现在我可以看到返回值 $result 只包含受第一个更新语句影响的行。所以我没有关于已删除行的任何信息,但我可以看到这些行确实在数据库中被删除了。

一般来说,如果我在 BEGIN TRAN、COMMIT TRAN 块中有一个 INSERT、DELETE、UPDATE 语句,并且如果整个块将由 DBI do() 方法提交,我需要知道插入语句的确切数量,更新的语句数和删除的语句数。

我知道 SQL SERVER 的 @@ROWCOUNT 会在每条语句之后给我受影响的行,但这是一个 SQL 服务器变量,仅在块内可见。是否可以将数据放入 perl 中?

有什么帮助吗?

【问题讨论】:

    标签: database perl transactions dbi


    【解决方案1】:

    要获取@@ROWCOUNT 的值,您需要在“COMMIT TRAN”之前添加SELECT @@ROWCOUNT 'rowcount' 作为最后一个命令,然后整个SQL 将返回由1 行和1 'rowcount' 列组成的结果集。

    唯一需要注意的是,由于do() 方法不为您提供结果集,因此您需要切换到prepare()/fetchrow_array()/fetchrow_array(),或者使用数据库库中的nsql() 之类的包装方法之一(如果有)可用。

    对于详细的插入/更新/删除细分,只需在插入/更新/删除后将这些 @@ROWCOUNT 保存到变量中,然后选择计数:

    declare @update_count int
    declare @delete_count int
    
    UPDATE table1 SET
    col1 = 999 where date = '2010-08-27'
    SELECT @update_count = @@ROWCOUNT
    
    DELETE FROM table1
    where date = '2010-08-30'
    SELECT @delete_count = @@ROWCOUNT
    
    SELECT @update_count 'update_count', @delete_count '@delete_count'
    

    【讨论】:

      【解决方案2】:

      正在使用什么数据库访问方法?是否有任何理由不将事务逻辑移到 T-SQL 之外?

      如果您正在使用 DBI,那么这些方面的内容应该可以满足您的要求:

      eval {
          $dbh->begin_work;
              $dbh->do("CREATE TABLE #temp (col1 INTEGER, date DATETIME);");
      
              # Inserts
              my $inserted = $dbh->do("INSERT INTO #temp VALUES (1,'2010-08-27');");
              $inserted += $dbh->do("INSERT INTO #temp SELECT 999,'2010-08-27' UNION SELECT 5, '2010-08-30';");
      
              # Updates
              my $updated = $dbh->do("UPDATE #temp SET col1 = 999 WHERE date = '2010-08-27';");
      
              # Deleted
              my $deleted = $dbh->do("DELETE FROM #temp WHERE date = '2010-08-30';");
          $dbh->commit;
      
          print "Inserted $inserted rows.\n";
          print "Updated $updated rows.\n";
          print "Deleted $deleted rows.\n"; }
      

      这个 sn-p 没有考虑建立数据库连接、错误处理或关闭连接,但 DBI 文档应该对此有所帮助。 http://metacpan.org/pod/DBI

      如果您计划执行多个非选择语句,您可能还想研究 prepare 和 bind_param DBI 方法。

      【讨论】:

      • 我有很多 INSERT、DELETE、UPDATE 作为单个事务运行。即为什么我需要在 T-SQL BEGIN TRAN 和 COMMIT TRAN 块中包含所有语句。所以我能想到的唯一方法是将整个 SQL 作为一个字符串,prepare() 它,执行并获取将有计数的返回结果。将在 begin_work 中执行多个操作并按照您所写的方式提交会产生相同的效果。完全是酸吗?
      • 是的,在 begin_work 和 rollback/commit 之间有多个 do 语句将与 T-SQL 中的 BEGIN TRANSACTION 和 ROLLBACK TRANSACTION/COMMIT TRANSACTION 块具有相同的效果。您可以通过将 $dbh->begin_work 替换为 $dbh->{AutoCommit} = 0; 来测试此行为,然后在不同的 DML 操作之后添加提交和回滚。无论事务是回滚还是提交,打印都会显示受影响的行数,但转储表结果应显示预期数据。
      猜你喜欢
      • 2012-05-02
      • 1970-01-01
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多