2015-08-31 12 views
6

Cụ thể, tôi cần xóa một số hàng khỏi bảng trong khi lặp qua tất cả các hàng trong bảng. Liệu DBI có một cái gì đó như một resultset updateable trong Java? Vì vậy, nếu tôi làm điều gì đó như:Có an toàn khi cập nhật bảng MySQL trong khi lặp lại kết quả với Perl DBI không?

$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 
    } 
} 

... OK?

Chỉ cần đưa ra một số ngữ cảnh, tôi sẽ xóa các hàng trùng lặp có cùng giá trị cho các cột X, Y, Z và chỉ để lại một hàng trong mỗi trường hợp (tìm thấy đầu tiên). Nếu đó là tất cả những gì tôi đã làm, tôi chỉ cần thiết lập một chỉ mục duy nhất trên 3 cột đó để loại bỏ các dups, nhưng tôi cũng cần xóa một hàng từ một bảng khác cho mỗi bản sao bị xóa khỏi MyTable. Cuối cùng, tôi đã viết một kịch bản để xác định và thu thập tất cả các ID cho các hàng mà tôi cần phải xóa vào một mảng, sau đó lặp qua mảng đó, xóa các hàng có liên quan khỏi cả hai bảng. Tôi vẫn muốn tìm câu trả lời cho câu hỏi ban đầu. Nếu tôi có thời gian, tôi sẽ tự mình trả lời, nhưng nếu có ai biết tôi muốn nghe nó.

+2

Bạn nên thêm trình kích hoạt xóa hàng tương ứng trong bảng phụ khi hàng bị xóa từ bảng chính. Sau đó, bạn có thể thêm ràng buộc duy nhất – Borodin

+0

Điều đó có vẻ giống như một giải pháp tốt, nhưng nó thực sự sẽ không phù hợp với tôi. Yêu cầu của tôi đã thay đổi một chút trong đó tôi cần phải giữ bản sao cuối cùng được thêm vào bảng thay vì đầu tiên, và tôi nghĩ rằng một ràng buộc duy nhất chỉ giữ đầu tiên. – RTF

Trả lời

1

Bạn đang lo lắng về một lỗi sửa đổi đồng thời?

Nếu bạn đang sử dụng giao dịch, sẽ không có vấn đề gì miễn là bạn lưu cam kết cho SAU KHI bạn đang thực hiện lặp lại.

Tuy nhiên nếu bạn đang sử dụng autocommit nó có thể là một vấn đề và vì vậy giải pháp sẽ là:

Pseudo Mã ish - không thử nghiệm

#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 
0

Một giải pháp khả thi sẽ là một cái gì đó cùng đoạn mã sau:

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 ([email protected]) { 
    print "Transaction rollback: [email protected]"; 
    $dbh->rollback(); 
} 
Các vấn đề liên quan