当跟踪中的语句返回 1 时,为啥 perl DBI 返回 0 行

Posted

技术标签:

【中文标题】当跟踪中的语句返回 1 时,为啥 perl DBI 返回 0 行【英文标题】:Why does perl DBI returns 0 rows when statement from trace returns 1当跟踪中的语句返回 1 时,为什么 perl DBI 返回 0 行 【发布时间】:2013-04-28 05:03:38 【问题描述】:

本周我第一次使用 perl DBI。

大部分查询/插入工作正常,但是我遇到了一个返回 0 行的特定查询的问题。当我为 perl DBI 启用跟踪,并将完全相同的语句从跟踪复制到服务器(通过 HeidiSQL)时,返回 1 行。

原始 SQL 查询是否存在歧义?目的是检索具有最新时间戳的行。时间戳列中没有重复项。

数据库连接的初始设置:

$dsn = 'dbi:mysql:<servername>:<port>';
$dbh = DBI->connect($dsn, "<username>","<password>") or die "unable to connect    $DBI::errstr\n";

准备和执行语句: 代码到达 print 'no rows found'

my $sth = $dbh->prepare("SELECT name, location, timestamp, notified FROM storage
  WHERE name = ? AND location = ? 
  AND timestamp = (SELECT MAX(timestamp) FROM storage)");

$sth->execute($strg_data->name, $strg_data->location);

my @latest = $sth->fetchrow_array();

if (@latest) 
   <snipped>

else 
  print "no rows found!\n";

从 perl DBI 跟踪中提取(级别设置为 2):

 -> prepare for DBD::mysql::db (DBI::db=HASH(0xebe4c0)~0xec0010 'SELECT name, location, timestamp, notified FROM storage
WHERE name = ? AND location= ? AND timestamp = (SELECT MAX(timestamp) FROM storage)')
Setting mysql_use_result to 0
<- prepare= DBI::st=HASH(0xecd7d0) at monitor.pl line 147
-> execute for DBD::mysql::st (DBI::st=HASH(0xecd7d0)~0xec9e50 'xxxx' '/tmp/')
-> dbd_st_execute for 00ecd7a0
  -> mysql_st_interal_execute
  Binding parameters: SELECT name, location, timestamp, notified FROM storage
WHERE name = 'xxxx' AND location= '/tmp/' AND timestamp = (SELECT MAX(timestamp) FROM storage)
  <- mysql_st_internal_execute returning rows 0
<- dbd_st_execute returning imp_sth->row_num 0
<- execute= '0E0' at monitor.pl line 152

【问题讨论】:

【参考方案1】:

SELECT MAX(timestamp) FROM storage 查找最大时间戳,而不考虑名称和位置。如果您指定的名称和位置没有具有该时间戳的记录,您将获得 0 行。

您可能想要此查询:

SELECT name, location, timestamp, notified FROM storage
  WHERE name = ? AND location = ? 
  ORDER BY timestamp desc LIMIT 1

【讨论】:

现在通过修改将 WHERE 子句添加到嵌套的 SELECT MAX(timestamp) 可以正常工作。我不清楚为什么我会从不同的 SQL 客户端获得返回的行——在这种情况下 perl DBI 和 HeidiSQL 的结果是否不匹配? 是的,ORDER BY 版本是合适的,并且可能比嵌套查询更可取——它肯定更容易阅读。 @user1792772,也许查询之间的表发生了变化。 是的,完全正确。刚刚意识到脚本的下一步是插入到同一个表中,这意味着当我的手动查询运行时,数据已经改变,并且有一个带有更新时间戳和匹配名称+位置的额外行。感谢您的帮助 看来你应该使用$dbh-&gt;last_insert_id【参考方案2】:

我知道这是一个旧线程,但我遇到了相同/相似的情况 - 我通过 perl dbi 的 mysql 查询返回 0 条记录,而命令行上的相同查询返回多个 (!)。

从 2003 年开始,我通过 google 搜索找到了这个问答:https://www.perlmonks.org/?node_id=312625 解决了我的问题 - 在 fetch 调用时使用“已定义”:

while (defined(my $data = $sth->fetchrow_array)) 

为什么使用 perl DBI 对同一个表进行相同的查询在查询某些列时返回数据但在某些其他列上不返回任何数据(如上所述)仍然是个谜。

【讨论】:

以上是关于当跟踪中的语句返回 1 时,为啥 perl DBI 返回 0 行的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Perl 中的 DBI 查询是不是返回了多个记录?

Perl DBI 何时关闭准备好的语句

Perl 执行 DBI 循环执行

为啥这个 ISQL 命令不能通过 Perl 的 DBI 运行?

Perl DBI - 使用多个语句运行 SQL 脚本

Perl DBI:带有 OR 语句的奇数绑定变量(需要 y 时使用 x 绑定变量调用)