perl + postgresql代码会导致Pg.pm出现问题

Jar*_*und 0 sql postgresql perl dbi

我在尝试将数据插入表中时遇到奇怪的错误,同时处理从不同表中获取的数据:

DBI::st=HASH(0x56261b345948)->_prepare(...): attribute parameter '0' is not a hash ref at /usr/lib/x86_64-linux-gnu/perl5/5.24/DBD/Pg.pm line 277.
Run Code Online (Sandbox Code Playgroud)

似乎导致它的行是上面代码片段中的$ dbh-> do():

 my $sth = $dbh->prepare(
     "SELECT (name, model), serial, firmware, timestamp FROM devicelog 
         WHERE id = $id AND fleet = $fleet AND timestamp >  
             (SELECT timestamp FROM devicelog WHERE fleet = $fleet AND id = $id ORDER BY timestamp DESC LIMIT 1)
             - INTERVAL '50 seconds'"
 );
 $sth->execute();
 while (my @row = $sth->fetchrow_array())
 {

     if (param('savetemplate'))
     {
         $dbh->do('INSERT INTO template (fleet, id, name, model, serial) VALUES (?, ?, ?, ?, ?)',
             $fleet,
             $id,
             $row[0],
             $row[1],
             $row[2]
         ) or die $!;
     }
     # Do some printing to screen and other mundane stuff
}
Run Code Online (Sandbox Code Playgroud)

我查看了第一个SQL查询返回的数据,但我发现它没有任何问题,因为结果会产生预期的结果:

                  row                   |  serial   |      firmware       |         timestamp          
----------------------------------------+-----------+---------------------+----------------------------
 ("HS60     GPS COMPASS",000-12308-001) | 19030590# |         01000023    | 2017-11-12 00:08:01.435483
 ("IS42     Instrument","")             | 007564#   | 01000_E 1.0.54.3.21 | 2017-11-12 00:08:01.476376
Run Code Online (Sandbox Code Playgroud)

我开始认为应该逃脱的东西不是吗?我还怀疑DBI可能不喜欢在迭代fetchrow_array()一系列的同时运行do(),但重写以避免同时执行它会产生相同的结果.

如果需要更多信息,请发表评论,我会提供.

mel*_*ene 6

根据文档,do有以下形式:

do

$rows = $dbh->do($statement)           or die $dbh->errstr;
$rows = $dbh->do($statement, \%attr)   or die $dbh->errstr;
$rows = $dbh->do($statement, \%attr, @bind_values) or die ...
Run Code Online (Sandbox Code Playgroud)

你的代码:

     $dbh->do('INSERT INTO template (fleet, id, name, model, serial) VALUES (?, ?, ?, ?, ?)',
         $fleet,
         $id,
         $row[0],
         $row[1],
         $row[2]
     )
Run Code Online (Sandbox Code Playgroud)

这将$fleet(第二个参数)视为对属性哈希(\%attr参数)的引用,它不是(它是一个数字).您不想传递任何属性,因此您应指定undef:

     $dbh->do('INSERT INTO template (fleet, id, name, model, serial) VALUES (?, ?, ?, ?, ?)',
         undef,
         $fleet,
         $id,
         $row[0],
         $row[1],
         $row[2],
     )
Run Code Online (Sandbox Code Playgroud)

另请注意,DBI没有设置$!,因此在错误消息中使用它没有多大意义.您应该使用$dbh->errstr(或者只是传递RaiseError => 1您的connect调用以使所有方法在出错时抛出异常).