2009-08-20 21 views
5

Bir SQL SELECT ifadesi tarafından döndürülen satırlarda bir döngüye sahibim ve bir satırın verileri üzerinde işlem yaptıktan sonra, bazen satırın değerini GÜNCELLEME istiyorum. Döngünün gövdesindeki işlem önemsizdir ve SQL'de yazamıyorum. Seçili satır için UPDATE'i çalıştırmayı denediğimde bir hata alıyorum (Perl'nin DBD :: SQLite :: st yürütme altında başarısız oldu: veritabanı tablosu kilitlendi). Yapmaya çalıştığım şeyi başarmak için okunabilir, verimli ve taşınabilir bir yol var mı? Başarısız, bunu yapmak için DBD veya SQLite özgü bir yolu var mı?Bir döngüde SELECT tarafından döndürülen satırları nasıl güncelleyebilirim?

Açıkçası, güncellemeleri ayrı veri yapısına alıp döngüden sonra çalıştırabilirim, ancak kodun bundan sonra da nefret etmesinden nefret ediyorum.

Eğer ilgileniyorsanız, burada ilgili Perl kodu.

my $q = $dbh->prepare(q{ 
    SELECT id, confLoc FROM Confs WHERE confLocId ISNULL}); 
$q->execute or die; 
my $u = $dbh->prepare(q{ 
    UPDATE Confs SET confLocId = ? WHERE id = ?}); 
while (my $r = $q->fetchrow_hashref) { 
    next unless ($r->{confLoc} =~ m/something-hairy/); 
    next unless ($locId = unique_name_state($1, $2)); 
    $u->execute($locId, $r->{id}) or die; 
} 
+0

Kullanımınız için çok kötü, Hazırda bekletmek istediğiniz şey için mükemmel olur. – Zoidberg

+2

İçsel olarak, kaçınmaya çalıştığım verimsiz operasyonu gerçekleştirecekti. –

+6

@Zoidberg, çok kötü yararsız yorumlar indiremeyiz. – friedo

cevap

6

geçici AutoCommit etkinleştirin:

 
sqlite> .header on 
sqlite> select * from test; 
field 
one 
two 
#!/usr/bin/perl 

use strict; 
use warnings; 

use DBI; 

my $dbh = DBI->connect('dbi:SQLite:test.db', undef, undef, 
    { RaiseError => 1, AutoCommit => 0} 
); 

test_select_with_update($dbh); 

sub test_select_with_update { 
    my ($dbh) = @_; 
    local $dbh->{AutoCommit} = 1; 
    my $q = $dbh->prepare(q{SELECT field FROM test}); 
    my $u = $dbh->prepare(q{UPDATE test SET field = ? WHERE field = ?}); 
    $q->execute or die; 
    while (my $r = $q->fetchrow_hashref) { 
     if ((my $f = $r->{field}) eq 'one') { 
      $u->execute('1', $f) or die; 
     } 
    } 
} 

kod çalıştırıldıktan sonra:

Zoidberg en comment ama senin geçiş mümkün olsaydı cevap
 
sqlite> .header on 
sqlite> select * from test; 
field 
1 
two 
2

Daha Perl'in DBIx::Class gibi bir ORM'ye o zaman sen cou olduğunu bulursun Böyle ld yazma şey:

my $rs = $schema->resultset('Confs')->search({ confLocId => undef }); 

while (my $data = $rs->next) { 
    next unless $data->confLoc =~ m/(something)-(hairy)/; 
    if (my $locId = unique_name_state($1, $2)) { 
     $data->update({ confLocID => $locid }); 
    } 
} 

Ve

DBIx :: Sınıf Fey::ORM gibi CPAN ve örneğin Rose::DB birkaç başkaları da vardır fantezi kapmak yoksa.

2

Sorununuz, bir alma döngüsündeyken bir güncelleştirme gerçekleştirmek için aynı veritabanı işleyicisini kullandığınızdır.

my $dbh = DBI->connect(...); 
my $dbhForUpdate = DBI->connect(...) ; 

Sonra döngüde dbhForUpdate kullanın:: Neyse

while(my $row = $sth->fetch()){ 
    ... 
    $dbhForUpdate->do(...) ; 
} 

, ben iyilik olduğunu çünkü bunu tavsiye etmem

Yani güncellemelerini gerçekleştirmek üzere veritabanı işleyicisi başka bir örneğini sahip veritabanı düzeyinde eşzamanlılık sorunları içine girme şansı.

İlgili konular