确定$ sth是否有行而不消耗它?

时间:2012-01-18 23:20:45

标签: perl dbi

使用DBI有一种方法可以确定SELECT语句的执行语句句柄是否会返回任何行而不从中获取?

即。类似的东西:

use DBI;
...
my $sth = $dbh->prepare("SELECT ...");
$sth->execute;

if (..$sth will return at least one row...) {
  ...
} else { 
  ...
}

我希望执行测试$sth will return at least one row 而不$sth上执行任何获取方法。

注意 - 我不需要确切的行数(即$sth->rows),我只需知道$sth->rows是否为> 0

4 个答案:

答案 0 :(得分:8)

$ sth->行仍然是您的最佳选择。如你所说,只是检查它是否超过0.

if ($sth->rows > 0){
  # magic here!
}

EXCEPT! DBI文档说,在获取所有行之前,这对于选择的状态是不可靠的。无法确定提前获取的行数。如果你需要知道这个,建议首先做一个

select count(*) from <table>

请参阅this section of the DBI documentation

答案 1 :(得分:2)

我认为没有任何可靠的方法来测试是否可以获取任何行而不是获取它们。当然,一旦你获取了第一行,它就不可用于获取,你必须“手持”它。但这并不难解决。

我一般认为使用以下两种习语之类的习语:

...
$sth->execute;

my @rows;

my $row = $sth->fetchrow_hashref();

if ($row) {
    do {
        # do something with $row
        ...

        $row = $sth->fetchrow_hashref();
    } while ($row);
} else {
    # No rows
}

...
$sth->execute;

my @rows;

while (my $row = $sth->fetchrow_hashref()) { push @rows, $row }

if (@rows) {
    # Some rows, now in @rows
} else { 
    # No rows
}

答案 2 :(得分:1)

您可以使用SQL来代替在DBI中查找内容。只需将SELECT包装到具有EXISTS条件的另一个SELECT中:

SELECT 1 FROM DUAL WHERE EXISTS ( SELECT ... );

它不是可移植的SQL:FROM DAL在您的RDBMS上可能看起来不同,您的数据库可能不支持EXISTS和子查询。但是,大多数现代数据库允许你做这样的事情。

它应该是最有效的方式,因为优化器可以跳过忽略对子查询的顺序,分组依据。检查执行计划。

SELECT COUNT(*) FROM ( SELECT ... )

也可以,但DB必须检查整个数据集以获得正确的行数。

如果您控制SQL构建器,那么您可以删除order by,group by(仅当没有部分时),并在其上应用限制以仅选择一行。

答案 3 :(得分:0)

也许这就是你要找的东西。

“Active”(布尔值,只读)

如果句柄对象为“活动”,则“活动”属性为true。这在应用程序中很少使用。活跃的确切含义目前有些模糊。对于数据库处理它通常        表示句柄连接到数据库(“$ dbh-&gt; disconnect”设置“Active”关闭)。对于语句句柄,它通常意味着句柄是一个“SELECT”,可能有更多的数据要提取。        (获取所有数据或调用“$ sth-&gt; finish”将“活动”设置为关闭。)