20

我正在尝试使用 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]东西上抛出了一个空数组引用错误。我怎样才能简单地检查它是否返回行或现在?

4

7 回答 7

38

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

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

这是特定于数据库驱动程序的,因此它可能在其他驱动程序中不起作用,或者在其他驱动程序中可能会有所不同。

于 2009-01-13T21:44:42.260 回答
13
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();
于 2009-01-13T21:12:49.533 回答
5

你为什么不只是“选择计数(*)......”?

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);
于 2009-01-13T23:45:48.507 回答
4

更改选择以始终返回某些内容?这应该在 Sybase 中工作,不知道其他数据库。

my $th = $dbh->prepare(qq{SELECT count(*) FROM bounce_info WHERE bi_exim_id = '$exid'});
$th->execute();
if ($th->fetch()->[0]) {
....
}
于 2009-01-13T21:24:26.203 回答
2

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

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'.

于 2009-01-13T21:59:21.467 回答
1

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

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

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

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

if ($sth->fetch) {
  # do stuff for one row returned
} else {
  # do stuff for no rows returned
}
于 2009-01-13T22:37:10.487 回答
1

本文可能对 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;

选择 FOUND_ROWS();

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

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

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

可悲的是,从 8.0.17 开始:

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

详情在这里

于 2012-11-07T10:33:04.643 回答