我在SQL SELECT语句返回的行上有一个循环,并且在对行的数据进行了一些处理之后,有时我想更新该行的值。循环主体中的处理非常重要,我无法用SQL编写。当我尝试为选定的行执行UPDATE时,我得到一个错误(在Perl的DBD :: SQLite :: st执行失败下:数据库表已锁定)。是否有一种可读,高效且可移植的方式来实现我要完成的任务?如果失败,是否有DBD或SQLite特定的方法来做到这一点?
显然,我可以将更新推送到单独的数据结构中,然后在循环之后执行它们,但是我讨厌代码的执行。
如果您有兴趣,这里是相应的Perl代码。
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; }
暂时启用AutoCommit:
AutoCommit
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; } } }
运行代码后:
sqlite> .header on sqlite> select * from test; field 1 two