【问题标题】:How do I know how many rows a Perl DBI query returns?我如何知道 Perl DBI 查询返回多少行?
【发布时间】:2020-04-20 21:35:35
【问题描述】:

我基本上是在尝试使用 Perl 在数据库中进行搜索,以判断是否存在具有特定 ID 的项目。此搜索可以不返回任何行,但也可以返回一个。

我有以下代码:

my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0] != $exid) {
        ...

基本上,这会尝试查看是否返回了 ID,如果没有返回,则继续执行脚本。但它在$th->fetch()->[0] 上抛出了一个空数组引用错误。 我怎样才能简单地检查它是返回行还是现在?

【问题讨论】:

  • 这确实与您正在使用的库有关......您可以更新您的问题以更具体。
  • @Robert,这与他使用的库无关。所有 ODBC 驱动程序的行为方式都相同。
  • 我希望这只是示例代码。但是你应该使用绑定值。

标签: mysql perl dbi


【解决方案1】:

DBD::mysql 驱动程序有一个rows() 方法可以返回结果的计数:

$sth = $dbh->prepare( ... );
$sth->execute;
$rows = $sth->rows;

这是特定于数据库驱动程序的,因此它可能不适用于其他驱动程序,或者它可能在其他驱动程序中以不同方式工作。

【讨论】:

  • DBI 有 rows() 方法,但是 rows() 在获取所有行之前不会为许多 DBD 中的 SELECT 返回有意义的结果。
  • 我们在这里讨论的是一个特定的 DBD。 :)
  • 啊,我现在看到了...隐藏在节点的标签中...如果这是问题的重要部分,它应该在标题或文本中:-)
【解决方案2】:
my $th = $dbh->prepare(qq{SELECT bi_exim_id FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
my $found = 0;
while ($th->fetch()) 
{
   $found = 1;
}

如果该行不存在,您的查询将不会返回任何内容,因此您无法取消对提取的引用。

更新:您可能希望将其重写为

my $found = $th->fetch();

【讨论】:

    【解决方案3】:

    你为什么不直接“select count(*) ...”??

    my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = '$exid'");
    

    或阻止Little Bobby Tables

    my $q_exid = $dbh->quote($exid);
    my ($got_id) = $dbh->selectrow_array("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = $q_exid");
    

    或者,如果您要经常执行此操作:

    my $sth = $dbh->prepare("SELECT count(*) from FROM bounce_info WHERE bi_exim_id = ?");
    ....save $sth (or use prepare_cached()) and then later
    my ($got_id) = $dbh->selectrow_array($sth, undef, $exid);
    

    【讨论】:

      【解决方案4】:

      改变选择总是返回一些东西?这应该在 Sybase 中工作,不知道其他数据库。

      my $th = $dbh->prepare(qq{SELECT count(*) FROM bounce_info WHERE bi_exim_id = '$exid'});
      $th->execute();
      if ($th->fetch()->[0]) {
      ....
      }
      

      【讨论】:

        【解决方案5】:

        总的来说,我不知道为什么人们如此害怕例外。你抓住他们并继续前进。

        my $sth = prepare ...
        $sth->execute;
        my $result = eval { $sth->fetchrow_arrayref->[1] };
        
        if($result){ say "OH HAI. YOU HAVE A RESULT." }
        else       { say "0 row(s) returned."         }
        

        不过,在这种情况下,保罗的回答是最好的。

        另外,$sth->rows 通常只有在您获取每一行之后才会起作用。如果您想知道有多少行匹配,那么您必须实际向数据库引擎询问您想知道答案的问题;即select count(1) from foo where bar='baz'

        【讨论】:

          【解决方案6】:

          找出 SELECT 查询返回多少行的唯一可靠方法是全部获取并计算它们。如the DBI documentation中所述:

          一般只能靠一行 非 SELECT 执行后计数(对于 一些特定的操作,如 UPDATE 和删除),或在获取所有 SELECT 语句的行。

          对于选择 声明,一般不会 可能知道有多少行 除非全部取回,否则返回。 一些驱动程序将返回的数量 应用程序已获取的行,所以 远,但其他人可能会返回 -1 直到 已获取所有行。所以使用 rows 方法或 $DBI::rows 与 不推荐使用 SELECT 语句。

          但是,当您开始着手时,无论如何您几乎不需要提前知道这一点。只需循环 while ($sth->fetch) 来处理每一行,或者对于只返回零或一行的查询的特殊情况,

          if ($sth->fetch) {
            # do stuff for one row returned
          } else {
            # do stuff for no rows returned
          }
          

          【讨论】:

          • "...无论如何,您几乎不需要提前知道这一点"——对于非常常见的结果分页情况,您需要提前知道有多少结果。
          • 我想看看我的程序已经读取/处理了多少条记录,在选择的记录总数中。如果我的选择抓取了 10,000 条记录,并且每分钟处理 100 条记录,那将需要一段时间。
          【解决方案7】:

          本文可能是 MySQL 8 之前版本的用户:

          http://www.arraystudio.com/as-workshop/mysql-get-total-number-of-rows-when-using-limit.html

          幸运的是,从 MySQL 4.0.0 开始,您可以在查询中使用 SQL_CALC_FOUND_ROWS 选项,这将告诉 MySQL 计算总行数而忽略 LIMIT 子句。您仍然需要执行第二个查询来检索行数,但这是一个简单的查询,不如检索数据的查询那么复杂。

          使用非常简单。在主查询中,您需要在 SELECT 之后添加 SQL_CALC_FOUND_ROWS 选项,在第二个查询中,您需要使用 FOUND_ROWS() 函数来获取总行数。查询如下所示:

          SELECT SQL_CALC_FOUND_ROWS 名称,来自用户的电子邮件 WHERE name LIKE 'a%' LIMIT 10;

          SELECT FOUND_ROWS();

          唯一的限制是您必须在第一个查询之后立即调用第二个查询,因为 SQL_CALC_FOUND_ROWS 不会在任何地方保存行数。

          虽然此解决方案也需要两个查询,但它的速度要快得多,因为您只需执行一次主查询。

          您可以在 MySQL 文档中阅读有关 SQL_CALC_FOUND_ROWS 和 FOUND_ROWS() 的更多信息。

          遗憾的是,从 8.0.17 开始:

          自 MySQL 8.0.17 起,SQL_CALC_FOUND_ROWS 查询修饰符和随附的 FOUND_ROWS() 函数已弃用 ...

          详情here.

          【讨论】:

            猜你喜欢
            • 2010-10-22
            • 2014-01-28
            • 2014-05-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多