如何在不运行两个单独的进程调用的情况下获取 DBI 中的行计数?

发布于 2024-07-20 02:46:33 字数 123 浏览 7 评论 0原文

我在 Perl 中运行 DBI,无法弄清楚当我运行准备好的语句时,我如何能够确定返回的行计数是否为 0。

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

I'm running DBI in Perl and can't figure out how, when I run a prepared statement, I can figure out if the returned row count is 0.

I realize I can set a counter inside my while loop where I fetch my rows, but I was hoping there was a less ugly way to do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

ら栖息 2024-07-27 02:46:33

快速查看此处,似乎在运行之后

$statement->execute($arg)

您可以通过以下方式访问行数

$statement->rows

Based on a quick look here, it seems that after you run

$statement->execute($arg)

you can access the row count via

$statement->rows
放我走吧 2024-07-27 02:46:33

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

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

对于 SELECT 语句,通常不可能知道将返回多少行,除非获取全部行。 某些驱动程序将返回应用程序迄今为止已获取的行数,但其他驱动程序可能会返回 -1,直到获取所有行为止。 因此,不建议将 rows 方法或 $DBI::rows 与 SELECT 语句一起使用。

The "caveat" in the documentation (linked to in a comment on another answer) is important, and provides the real, correct answer:

Generally, you can only rely on a row count after a non-SELECT execute (for some specific operations like UPDATE and DELETE), or after fetching all the rows of a SELECT statement.

For SELECT statements, it is generally not possible to know how many rows will be returned except by fetching them all. Some drivers will return the number of rows the application has fetched so far, but others may return -1 until all rows have been fetched. So use of the rows method or $DBI::rows with SELECT statements is not recommended.

池予 2024-07-27 02:46:33

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

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

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

所以,没有什么花哨的方法可以得到这个结果。 你只需要数一下它们就可以了:-)

In order to find out how many rows are in a result set you have exactly two options:

  1. select count(*)
  2. Iterate over the result set and count the rows.

You can introduce some magic via a stored procedure that returns an array or something more fancy, but ultimately one of those two things will need to happen.

So, there is no fancypants way to get that result. You just have to count them :-)

十秒萌定你 2024-07-27 02:46:33

虽然有点晚了,但如果有人使用 ORACLE,那么解决方案就来了:

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

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

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

这也是在 Oracle 中进行启动和限制的一种非常简单的方法,并且仍然可以获得完整的行数:

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 开始)和完整计数(没有开始和限制)排。

It's a bit late, but if anyone uses ORACLE, here comes THE sweat solution:

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

$sql is your query, of course. Oracles optimizer is intelligent enough not to execute everything twice.

Now every fetched row holds the current row number (useful for paging grid row numbering) in DB_ROWNUM and the complete number of rows in DB_COUNT. You still have to fetch at least one row (so it isn't exactly the answer to the question above ;)), but the sweat use comes next:

It's also a very easy way to do start and limit in Oracle and still get the complete number of rows:

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

With this, you can actually fetch only row 51 to 100 for the second page in your grid, but still have the real row number (starting from 1) and the complete count (without start and limit) in every fetched row.

你穿错了嫁妆 2024-07-27 02:46:33

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

select null, null, null, count(*) from tablex
union
select foo, bar, foobar, null from tablex

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

try this SQL solution, combine your SQL for the data with a count Statement.

select null, null, null, count(*) from tablex
union
select foo, bar, foobar, null from tablex

the first statement will have the count, and should be the first row (if not you can order by to get around it) then you can cycle through the rest of the recordset at your leisure.

撩人痒 2024-07-27 02:46:33

CPAN 说:

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

所以做这样的事情可能会起作用:

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

say (scalar keys %{$sth->fetchall_hashref('id')}) . ' row(s).';

CPAN says:

[...] or after fetching all the rows of a SELECT statement.

So doing something like this will probably work:

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

say (scalar keys %{$sth->fetchall_hashref('id')}) . ' row(s).';
东走西顾 2024-07-27 02:46:33

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

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

--
沙昆塔拉

I have dynamically generated a SQL and executing it. For me select count(*) does not seem to be an option because I have to re-generate the query again. Following approach looked clean for me. But you have to issue s $h->execute() once again to retrieve row data.

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

--
Shaakunthala

一直在等你来 2024-07-27 02:46:33

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

Rows definitely does vary depending on the database/driver version it seems. I would definitely look to a piece of logic there that dealt with unexpected results.

挽手叙旧 2024-07-27 02:46:33

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

在第一个查询中,在 SELECT 之后添加 SQL_CALC_FOUND_ROWS。 然后执行SELECT FOUND_ROWS();,您就可以立即访问行数。 现在您可以决定是要遍历所有行,还是最好的方式。

请注意,查询中包含 LIMIT 将为您提供没有 LIMIT 时查询返回的总数。

If you want to know how many rows are there before walking through all of them, a MySQL-specific solution could be FOUND_ROWS().

In your first query, add SQL_CALC_FOUND_ROWS right after SELECT. Then do SELECT FOUND_ROWS();, and you have access to the row count right away. Now you can decide whether you want to walk through all the rows, or the best way to do it.

Note that having LIMIT in the query will give you the total number query would have returned without LIMIT.

自由如风 2024-07-27 02:46:33

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

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

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";
    }
}

As others already said, you really need to get the rows to find out if there are any. If you need to know before starting a loop on every row, and if the expected results are not huge, you can get all results into an array, and then check that.

I recently used something like that:

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";
    }
}
满天都是小星星 2024-07-27 02:46:33

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

$year='2018';
my $qry = "SELECT COUNT(`my_key`) FROM `mtable` WHERE `my_date` LIKE '$year-01-%';";
my ($count) = $dbc->selectrow_array($qry);

I'd just let the database do the counting instead. If all you want is the number of rows.
Find all the rows for january 2018.

$year='2018';
my $qry = "SELECT COUNT(`my_key`) FROM `mtable` WHERE `my_date` LIKE '$year-01-%';";
my ($count) = $dbc->selectrow_array($qry);
臻嫒无言 2024-07-27 02:46:33

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

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";
}

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

I think this can be achieved pretty easily using references.
The code blow below shows how it is not needed to go for re-execution of the query to fetch the rows after a count.

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";
}

I hope this satisfied the question made here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文