一尘不染

如何在循环中更新SELECT返回的行?

sql

我在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;
}

阅读 161

收藏
2021-05-23

共1个答案

一尘不染

暂时启用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
2021-05-23