Perl DBI - 获取事务中每个语句影响的记录

Posted

技术标签:

【中文标题】Perl DBI - 获取事务中每个语句影响的记录【英文标题】:Perl DBI - Getting records affected of each statement in a transaction 【发布时间】: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 中?

有什么帮助吗?

【问题讨论】:

【参考方案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 操作之后添加提交和回滚。无论事务是回滚还是提交,打印都会显示受影响的行数,但转储表结果应显示预期数据。

以上是关于Perl DBI - 获取事务中每个语句影响的记录的主要内容,如果未能解决你的问题,请参考以下文章

吴裕雄 27-MySQL 元数据

Perl DBI 何时关闭准备好的语句

Perl DBI:带有 OR 语句的奇数绑定变量(需要 y 时使用 x 绑定变量调用)

Perl DBI - 使用多个语句运行 SQL 脚本

当 Perl 的 DBI 在准备语句时遇到错误时,如何避免程序退出?

Perl DBI 语句句柄和错误处理