poolboi has asked for the wisdom of the Perl Monks concerning the following question:

Hi guys, i've got the following code below
$sth = $dbh->prepare("SELECT * FROM `mml log` WHERE Commands LIKE '%$I +MSI%'"); $sth->execute(); my $numFields = $sth->{'NUM_OF_FIELDS'}; while (my $ref = $sth->fetchrow_arrayref){ for (my $i=0; $i<$numFields; $i++){ printf ("%s %s", $i ? "," : "", $$ref[$i]); } }
it prints the results from mysql if i find a match but say i am unable to find a match i want to output to users " sorry no matches found"
i need a (if..else) statement..but how do i determine if the fetchrow_arrayref is empty in the condition of the if..else statement?

Replies are listed 'Best First'.
Re: how to determine of fetchrow_Arrayref is empty?
by ysth (Canon) on May 27, 2008 at 02:09 UTC
    Lots of ways. A few:
    my $matches = 0; while (...) { ++$matches; ... } if (! $matches) { ... "sorry no matches found" }
    or
    my $command = $sth->fetchrow_arrayref(); if (! $command) { ... "sorry no matches found" } else { do { for (...) { printf ... } } while ($command = $sth->fetchrow_arrayref()); }
    or
    my $first = 1; while ( (my $command = $sth->fetchrow_arrayref) || $first ) { if (! $command) { ... "sorry no matches found" $first = 0; } else { for ... } }
Re: how to determine of fetchrow_Arrayref is empty?
by GrandFather (Saint) on May 27, 2008 at 02:01 UTC

    $ref is a reference to an array so you can:

    if (@$ref) { # have elements } else { # No elements to process }

    See perlreftut and perlref.


    Perl is environmentally friendly - it saves trees
Re: how to determine of fetchrow_Arrayref is empty?
by doom (Deacon) on May 27, 2008 at 02:17 UTC
    fetchrow_arrayref returns a defined reference only if there are rows in the result set, if not it's undefined. So you just need to replace the "while" with something like
    if ( not( $ref ) ) { print "No results\n"; } else { # code to print results }

    If I may offer some observations about the way you're doing this:

    (1) The variable $numFields would be better named $number_fields. See perlstyle. And you might want to change "$ref" to "$aref" to indicate what kind of reference it is (myself, I'd probably call it $row, though I think Conway prefers $row_ref).

    (2) The C-style for loop over the fields might be clearer if done in a more perl like way, just for example:

    my $result = join ", ", @{ $ref }; print $result, "\n";

    (3) Personally I lean towards fetchrow_hashref these days: the performance penalty on that was fixed a long time ago.

      fetchrow_hashref wouldn't work with what the OP is doing for each row (at least, not without a lot of hassle).

        The OP hasn't actually made the ultimate goal clear -- my guess would be that a comma separated list of all fields is just an intermediate step while learning how to use DBI.

        Starting with fetchrow_hashref and using a stub like this is probably a better place to begin:

        foreach my $field_name (keys %{ $row_href }) { my $value = $row_href->{ $field_name }; print "$field_name: $value \n"; }

        And if the order of the fields is important, you can replace keys %{ $row_href } with an array @field_names... typically, you have that information already, since you need it to build the SELECT.

Re: how to determine of fetchrow_Arrayref is empty?
by hesco (Deacon) on May 27, 2008 at 07:09 UTC
    And while we're exploring the possibilities presented by TIMTOWTDI, try reading perldoc DBI for the ->rows() method, as well. You might find it helpful. I seem to remember some caveat about certain conditions under which ->rows() wasn't useful in the perldoc. But the details escape me now. From memory, and untested, it would go something like this:

    if(!$sth->rows()){ print STDERR "sorry no matches found\n"; } else { # do something useful with data }
    -- Hugh

    if( $lal && $lol ) { $life++; }
      DBI:
        $rv = $sth->rows;

      Returns the number of rows affected by the last row affecting command, or -1 if the number of rows is not known or not available.

      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.

      So it should work to do
      if (! $sth->rows) { print "sorry, no matching data" }
      after the while loop.