2010-09-10 57 views
2

我正在使用這種方法。如果sql中有錯誤,則回滾僅發生在asset_group的第一個id上。其餘的ID被忽略。我是否正確地做?perl dbi回滾不起作用

my $sql = "sql batch that update and insert depending on the condition"; 
$dbh->{RaiseError} = 1; 
$dbh->{PrintError} = 0; 
$dbh->{AutoCommit} = 0; 

my $sth = $dbh->prepare($sql); 
my @error =(); 
my $num = 0; 
foreach my $id (@asset_group) { 
next if ($id eq ''); 
eval { 
    $sth->bind_param(1, $id); 
    $sth->bind_param(2, $vars{'other_id'}); 
    $sth->execute(); 

}; 
if ([email protected]) { 
    $dbh->rollback(); 
    push @error, [email protected] 
} else { 
    $dbh->commit(); 
} 
} 
+1

你是什麼意思「其餘的ID被忽略?」 – cam 2010-09-10 16:47:22

+0

即使您關閉了AutoCommit,您可能也希望使用'BEGIN'和'END/COMMIT/ROLLBACK'明確設置事務。你正在使用哪些DBMS? – vol7ron 2010-09-10 17:27:45

+0

小心,提交也會失敗。 – bohica 2010-09-13 08:40:46

回答

7

根據數據庫的不同,您可能需要在開始更改之前發出begin work。我似乎記得Informix需要一個。

另外,它看起來像是在每次執行後發出提交或回滾。一旦提交,就不能回滾。通常有人說類似

$dbh->begin_work; 
eval { 
    for my $id (@asset_group) { 
     next if ($id eq ''); 
     $sth->execute($id, $vars{other_id}); 
    } 
    1; #if it doesn't die then this will force it to return true 
} or do { 
    my $error = DBI->errstr; 
    $dbh->rollback(); 
    die "could not insert rows: $error\n" 
}; 
$dbh->commit(); 

注意我怎麼不使用[email protected][email protected]untrustworthy

+0

你不需要調用'begin_work'。它的存在主要是爲了允許您爲特定的一組操作使用事務,即使您打開了AutoCommit。在AutoCommit關閉的情況下(就像這裏),如果數據庫不支持事務處理,它所做的全部事情都會消失。但你的答案的其餘部分是很好的建議。 – cjm 2010-09-10 17:38:02

+0

謝謝大家。有效。 – alp 2010-09-10 18:06:26

+1

@alp,那麼您應該通過點擊其分數附近的複選標記來將答案標記爲已接受。 – cjm 2010-09-10 18:12:31