12

我在 Perl 中运行 DBI,但无法弄清楚当我运行准备好的语句时,我如何知道返回的行数是否为 0。

我意识到我可以在我的 while 循环中设置一个计数器来获取我的行,但我希望有一种不那么丑陋的方法来做到这一点。

4

12 回答 12

20

根据这里的快速浏览,似乎在你运行之后

$statement->execute($arg)

您可以通过访问行数

$statement->rows
于 2009-05-12T22:20:15.677 回答
12

文档中的“警告”(链接到另一个答案的评论中)很重要,并提供了真实、正确的答案:

通常,您只能在-SELECT 执行(对于某些特定操作,如 UPDATE 和 DELETE)之后或在获取 SELECT 语句的所有行之后依赖行计数。

对于 SELECT 语句,通常不可能知道将返回多少行,除非全部获取它们。一些驱动程序将返回应用程序到目前为止已获取的行数,但其他驱动程序可能会返回 -1,直到所有行都已获取。因此不推荐使用带有 SELECT 语句的 rows 方法或 $DBI::rows。

于 2009-05-13T03:05:33.200 回答
9

为了找出结果集中有多少行,您有两个选项:

  1. select count(*)
  2. 遍历结果集并计算行数。

您可以通过返回数组或更花哨的存储过程引入一些魔法,但最终需要发生这两件事中的一件。

所以,没有花哨的方法来获得这个结果。你只需要数一数:-)

于 2009-05-13T21:17:25.053 回答
4

有点晚了,但是如果有人使用 ORACLE,那么汗水解决方案来了:

SELECT
  q.*,
  ROWNUM DB_ROWNUM,
  (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
FROM
  ($sql) q

当然,$sql 是您的查询。Oracles 优化器足够智能,不会执行所有操作两次。

现在,每个获取的行都在 DB_ROWNUM 中保存当前行号(对分页网格行编号有用),在 DB_COUNT 中保存完整的行数。您仍然必须获取至少一行(因此它不完全是上述问题的答案;)),但接下来是汗水使用:

这也是在 Oracle 中进行 start 和 limit 并仍然获得完整行数的一种非常简单的方法:

SELECT * FROM (
  SELECT /*+ FIRST_ROWS($limit) */
    q.*,
    ROWNUM DB_ROWNUM,
    (SELECT max(ROWNUM) FROM ($sql)) DB_COUNT
  FROM
    ($sql) q
  WHERE
    ROWNUM <= $limit
)
WHERE
  DB_ROWNUM > $start

有了这个,您实际上只能为网格中的第二页获取第 51 到 100 行,但在每个获取的行中仍然有真实的行号(从 1 开始)和完整的计数(没有开始和限制)。

于 2013-04-17T11:13:05.123 回答
2

试试这个 SQL 解决方案,将数据的 SQL 与 count 语句结合起来。

从 tablex 中选择 null、null、null、count(*)
联盟
从 tablex 中选择 foo、bar、foobar、null

第一条语句将具有计数,并且应该是第一行(如果不是,您可以订购绕过它)然后您可以在闲暇时循环浏览记录集的其余部分。

于 2012-01-04T23:23:18.033 回答
2

CPAN 说:

[...] 或在获取 SELECT 语句的所有行之后。

所以做这样的事情可能会奏效:

$sth->execute or die $sth->errstr;

say (scalar keys %{$sth->fetchall_hashref('id')}) . ' row(s).';
于 2014-03-23T15:33:09.260 回答
1

我已经动态生成了一个 SQL 并执行它。对我来说select count(*)似乎不是一个选择,因为我必须再次重新生成查询。以下方法对我来说看起来很干净。但是您必须$h->execute()再次发出 s 才能检索行数据。

$h->execute() or die "ERROR: Couldn't execute SQL statement";
$rowcount_ref = $h->fetchall_arrayref(0);
$rowcount = scalar (@{$rowcount_ref});

——沙昆塔拉

于 2013-02-07T14:16:41.217 回答
0

行肯定会根据看起来的数据库/驱动程序版本而有所不同。我肯定会在那里寻找一个处理意外结果的逻辑。

于 2009-05-12T23:30:46.933 回答
0

我只是让数据库进行计数。如果你想要的只是行数。查找 2018 年 1 月的所有行。

$year='2018';
my $qry = "SELECT COUNT(`my_key`) FROM `mtable` WHERE `my_date` LIKE '$year-01-%';";
my ($count) = $dbc->selectrow_array($qry);
于 2018-08-09T07:20:35.890 回答
0

我认为这可以很容易地使用引用来实现。下面的代码显示了如何不需要重新执行查询来获取计数后的行。

my $sth = $dbh->prepare("SELECT NAME, LOCATION
                        FROM Employees"); 
$sth->execute() or die $DBI::errstr;

$nrows =  $sth->fetchall_arrayref() ;

print "Number of rows found :" . @$nrows . "\n";

#while (my @row = $sth->fetchrow_array()) {

foreach my $row(@{$nrows}) {
   my ($name, $location ) = @$row;
   print " Name = $name, Location = $location\n";
}

我希望这能满足这里提出的问题。

于 2021-01-13T11:35:37.383 回答
0

如果您想在遍历所有行之前知道有多少行,特定于 MySQL 的解决方案可能是FOUND_ROWS()

在您的第一个查询中,SQL_CALC_FOUND_ROWSSELECT. 然后执行SELECT FOUND_ROWS();,您可以立即访问行数。现在您可以决定是否要遍历所有行,或者最好的方法。

请注意,LIMIT在查询中包含 将为您提供不带LIMIT.

于 2017-08-11T15:05:08.457 回答
0

正如其他人已经说过的那样,您确实需要获取行以找出是否有任何行。如果您需要在对每一行开始循环之前知道,并且如果预期结果不是很大,您可以将所有结果放入一个数组中,然后检查。

我最近使用了类似的东西:

foreach my $table ( qw(ACTOR DIRECTOR PRODUCER WRITER) ) {
    my $sth = $dbi->prepare(qq{SELECT * FROM $table WHERE DESCRIPTION != TRIM(DESCRIPTION)})
        or die $dbi->errstr;
    $sth->execute or die $sth->errstr;

    my @rows = @{ $sth->fetchall_arrayref() };

    next unless @rows;

    foreach my $row (@rows) {
        print join(", ", map {qq("$_")} @{$row}), "\n";
    }
}
于 2017-12-06T16:28:28.307 回答