如何检查数据库查询是否会返回结果?

时间:2008-11-14 13:49:29

标签: perl dbi rows

我们的网站使用Perl为我们的人力资源人员提供一个简单的机制,以便将空缺职位发布到我们的网站。它是由第三方开发的,但是它们很久以来就被触碰了,遗憾的是我们内部没有任何Perl技能。当营销人员规避他们的内部IT团队时会发生这种情况!

我需要对此应用程序进行简单的更改。目前,职位空缺页面上写着“我们目前有以下职位空缺:”,无论是否有职位空缺!所以我们想要改变它,以便只在适当的时间显示这一行。

显然,我可以开始学习一点Perl,但我们已经在计划一个替换站点,它肯定不会使用Perl。因此,对于具有这些技能的人来说,解决方案将是微不足道的,我想我会要求一些有针对性的帮助。

以下是列出职位空缺的程序的开始。

sub list {
  require HTTP::Date;
  import HTTP::Date;

  my $date = [split /\s+/, HTTP::Date::time2iso(time())]->[0];

  my $dbh = DBI->connect($dsn, $user, $password)
    || die "cannot connect to $database: $!\n";

  my $sql = <<EOSQL;
SELECT * FROM $table where expiry >= '$date' order by expiry
EOSQL

  my $sth = $dbh->prepare($sql);
  $sth->execute();


  while (my $ref = $sth->fetchrow_hashref()) {
    my $temp  = $template;
    $temp     =~ s#__TITLE__#$ref->{'title'}#;

    my $job_spec = $ref->{'job_spec'};

...etc...

关键是while (my $ref = $sth->fetchrow_hashref()) {。我想这是在说“我可以从退回的记录集中取出另一个空位......”。如果我在此行之前放置我的print语句,它将始终显示;在这一行之后,每个空缺都会重复。

如何确定是否有一些空位要显示,而不会过早地移动返回的记录集?

我总是可以在while循环中复制代码,并将它放在if()循环中的if()语句中,该语句也包含我的print语句。但我更愿意采用更简单的If any records then print "We currently have.." line方法。不幸的是,即使是这条简单的行,我也没有线索。

看,我告诉过你,这是一个微不足道的问题,即使考虑到我的错误解释!

TIA

克里斯

9 个答案:

答案 0 :(得分:15)

一个非常简单的方法是:

$sth->execute();

my $first = 1;
while (my $ref = $sth->fetchrow_hashref()) {
    if( $first ) {
        print "We currently have the following vacancies:\n";
        $first = 0;
    }
    my $temp  = $template;
    ...
}
if( $first ) {
    print "No vacancies found\n";
}

答案 1 :(得分:3)

这不是一个Perl问题,因为它是一个数据库问题,并且没有好的方法可以知道你拥有它们之前有多少结果。你有两个选择:

  1. 执行“select count(*)”查询以查看有多少行,然后执行另一个查询以获取实际行或
  2. 执行查询并将结果存储到哈希中,然后计算哈希中有多少条目,然后浏览哈希并打印出结果。
  3. 例如,脱离我的头顶:

    my @results = ();
    while (my $ref = $sth->fetchrow_hashref()) {
       push @results, $ref;
    }
    
    if ($#results == 0) {
      ... no results
    } else {
      foreach $ref (@results) {
        my $temp = $template;
        ....
     }
    

答案 2 :(得分:3)

如果你使用的是Mysql,那么“rows”方法就可以了:

$sth->execute();

if($sth->rows) {
  print "We have data!\n";
}

while(my $ref = $sth->fetchrow_hashref()) {
...
}

该方法和一些注意事项在“perldoc DBI”中有详细记录。始终以“perldoc”开头。

答案 3 :(得分:2)

由于每个人都希望优化掉Graeme解决方案中是否已经打印标题的重复测试,我会在上面提出这个小变化:

$sth->execute();

my $ref = $sth->fetchrow_hashref();
if ($ref) {
  print "We currently have the following vacancies:\n";
  while ($ref) {
    my $temp  = $template;
    ...
    $ref = $sth->fetchrow_hashref();
  }
} else {
    print "No vacancies found\n";
}

答案 4 :(得分:2)

由于您的查询是 SELECT ,因此您无法利用rowsexecute本身返回的值。

但是,您可以通过添加另一个查询来预先计算您的查询将选择多少行(即空位)......如下所示:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?";
$sth = $dbh->prepare($query);
$sth->execute($date);
$numVacancies = $numinfo->fetchrow_arrayref()->[0];

# Debug:
print "Number of vacancies: " . $numVacancies . "\n";

if ( $numVacancies == 0 ) { # no vacancy found...
    print "No vacancies found!\n";
}
else { # at least a vacancy has been found...
    print "We currently have the following vacancies:\n";

    # Retrieve the vacancies:
    my $sql = "SELECT * FROM $table where expiry >= '$date' ORDER BY expiry";
    my $sth = $dbh->prepare($sql);
    $sth->execute();

    ...
}

或者,类似地,而不是&#34;准备&#34; &#34;执行&#34; 查询,然后使用&# 34; fetchrow_array&#34; ,您可以使用selectrow_array在一次通话中完成所有操作:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?"; 
my $numVacancies = $dbh->selectrow_array($query, undef, $date);

# Debug:
print "Number of vacancies: " . $numVacancies . "\n";

selectall_arrayref同样如此:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?";
my $numVacancies = $dbh->selectall_arrayref($query, {Slice => {}}, $date);

# Debug:
print "Number of vacancies: " . @$numVacancies[0]->{rows} . "\n";

但是,如果您使用 selectrow_array selectall_arrayref ,您还可以直接从原始查询的结果中检索空缺数量:

# Retrieve the vacancies:
my $sql = "SELECT * FROM $table where expiry >= ? ORDER BY expiry";
my $vacancies = $dbh->selectall_arrayref($sql, {Slice => {}}, $date);

# Debug:
print "Number of vacancies: " . scalar @{$vacancies} . "\n";

答案 5 :(得分:1)

更有效的方法(避免循环中的条件),如果你不介意它改变页面输出的方式(一次一个而不是一次一行)你可以做一个变量在循环之前保持输出:

my $output = '';

然后在循环内部,将任何print语句更改为:

$output .= "whatever we would have printed";

然后循环:

if ($output eq '')
{
  print 'We have no vacancies.';
}
else
{
  print "We currently have the following vacancies:\n" . $output;
}

答案 6 :(得分:1)

只需添加另一个查询......就像这样:

# count the vacancies    
$numinfo = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE EXPIRY >= ?");
$numinfo->execute($date);
$count = $numinfo->fetchrow_arrayref()->[0];

# print a message
my $msg = '';
if   ($count == 0) $msg = 'We do not have any vacancies right now';
else               $msg = 'We have the following vacancies';
print($msg);

答案 7 :(得分:1)

use Lingua::EN::Inflect 'PL';

$sth->execute();
my $results = $sth->fetchall_arrayref( {}, $max_rows );

if (@$results) {
    print "We currently have the following ", PL("vacancy",scalar @$results), ":\n";

    for my $ref (@$results) {
        ...
    }
}

答案 8 :(得分:-2)

perldoc DBI说:

 For a non-"SELECT" statement, "execute" returns the number of rows
 affected, if known. If no rows were affected, then "execute"
 returns "0E0", which Perl will treat as 0 but will regard as true.

所以答案是检查$ sth-&gt; execute()的返回值:

 my $returnval = $sth->execute;
 if (defined $returnval && $returnval == 0) {
     carp "Query executed successfully but returned nothing";
     return;
 }