在使用Perl DBI迭代结果集时更新MySQL表是否安全?

时间:2015-08-31 09:21:01

标签: perl dbi

具体来说,我需要在迭代表中的所有行时从表中删除一些行。 DBI在Java中有类似可更新结果集的东西吗?所以,如果我做了类似的事情:

$query_all = $dbh->prepare("select Id, X, Y, Z from MyTable");
$delete = $dbh->prepare("delete from MyTable where Id = ?");
$query_all->execute();

while ( my @res = $query_all->fetchrow_array() ){
    my ($id, $x, $y, $z) = @res;
    # fetch the IDs of any other rows that have the same X, Y, Z values
    foreach ( the_duplicate_ids ){
        $delete->execute($dup_id); # safe ??
        # also delete from another table using $dup_id
    }
}

......那可以吗?

为了给出一些上下文,我删除了对X,Y,Z列具有相同值的重复行,并且在每种情况下只留下一行(找到第一行)。如果这就是我正在做的事情,我只是在这3列上设置一个唯一索引以消除重复,但我还需要从另一个表中删除从MyTable删除的每个重复的行。 / p>

最后,我编写了一个脚本来识别和收集我需要删除到数组中的行的所有ID,然后迭代该数组,删除两个表中的相关行。我仍然有兴趣找到原始问题的答案。如果我有时间,我会尝试自己回答,但如果有人已经知道我想听听它。

2 个答案:

答案 0 :(得分:1)

您是否担心并发修改错误?

如果您正在使用交易,只要您在完成迭代后保存提交,它就不会成为问题。

但是,如果您使用自动提交,则可能是一个问题,因此解决方案将是:

伪代码 - 未经测试

#Loop through each row and note the records to delete
my @deathrow = ();
foreach my $row ( @resultset ) {
    push $row->{id}, @deathrow;
}

#Now that we're done iterating, do all the deletes in one statement
$dbh->execute("DELETE WHERE id IN ( " . @deathrow . " )"); #something like that

答案 1 :(得分:0)

一个可能的解决方案是以下代码段:

my $dbh = DBI->connect("DBI:mysql:database=XXXX;host=localhost", "user", "pass", {'RaiseError' => 1, 'AutoCommit' => 0});

my $query_all = $dbh->prepare("select Id, X, Y, Z from MyTable");

eval {
    my $delete = $dbh->prepare("delete from MyTable where Id = ?");
    $query_all->execute();
    while ( my @res = $query_all->fetchrow_array() ){
        my ($id, $x, $y, $z) = @res;
        # fetch the IDs of any other rows that have the same X, Y, Z values
        foreach my $dup_id (@the_duplicate_ids){
            $delete->execute($dup_id); # safe ??
            # also delete from another table using $dup_id
        }
    }    
    $dbh->commit();
};

if ($@) {
    print "Transaction rollback: $@";
    $dbh->rollback();
}