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

Hi, I am having trouble with this: each select statement executed will fetch multiple records with same tax_id(see below) value. I want to catch only single of 'em. some how it not getting in to elsif($count==1) loop. I am unable to figure out why? please let me know,
my $refseq_list ="/home/bla/bla/refseq.txt"; open(REF,$refseq_list); my($ref,@ref,$size,$command1); while($ref=<REF>) { push(@ref,$ref); } $size = @ref; print "$size sequences found\n"; my $count=0; LOOP:foreach $ref(@ref) { print "in foreach loop\n"; $count=0; $command1 = qq{select tax_id from gene2acc where genomic_ac_ver= '$r +ef'; }; $sth1=$dbh->prepare($command1); $sth1->execute() or die $sth1->errstr; my($tax_id); $sth1->bind_columns(undef,\$tax_id ); while($array=$sth1->fetchrow_array()) { $count++; if($sth1->rows == 0) { print "No records matched for $ref\nn"; } elsif($count==1) { $t=$array; print "Entering taxID_format with $t\n"; #&taxID_format($t); } }

Replies are listed 'Best First'.
Re: dbi retieve single col value
by pjotrik (Friar) on Aug 28, 2008 at 11:07 UTC
    To select every value of tax_id only once, use
    SELECT DISTINCT tax_id FROM gene2acc WHERE genomic_ac_ver = ?
    or
    SELECT tax_id FROM gene2acc WHERE genomic_ac_ver = ? GROUP BY tax_id
      Hi thanks I tried this way,it still does not enter the while loop to print the statement:print "Entering taxID_format with $t\n";
      LOOP:foreach $ref(@ref) { print "in foreach loop with $ref\n"; $count=0; $command1 = qq{select distinct tax_id from gene2acc where genomic_ac +_ver= '$ref'; }; $sth1=$dbh->prepare($command1); $sth1->execute() or die $sth1->errstr; my($tax_id); $sth1->bind_columns(undef,\$tax_id ); while($sth1->fetch()) { $t=$tax_id; print "Entering taxID_format with $t\n"; #&taxID_format($t); }
      please help me
Re: dbi retieve single col value
by gone2015 (Deacon) on Aug 28, 2008 at 11:24 UTC

    DBI->trace() looks like a good place to get some more information about what's going on.

    I was puzzled by this:

    $count = 0 ; .... while($array = $sth1->fetchrow_array()) { $count++ ; if ($sth1->rows == 0) { print "No records matched for $ref\nn" ; } elsif ($count == 1) { $t = $array ; print "Entering taxID_format with $t\n" ; #&taxID_format($t) ; } }
    I find that $array = $sth1->fetchrow_array() fetches the next row, and sets $array to the value of the first field, or undef if no more rows. Leaving aside the possibility that a row may have an undef first column (or '0')... I don't see the purpose of the if ($sth->rows == 0). Further, I note that the documentation (http://search.cpan.org/~timb/DBI-1.607/DBI.pm#rows) says: "Generally, you can only rely on a row count after a non-SELECT execute ..., or after fetching all the rows of a SELECT statement.".

    That said, unless the $sth->rows returns 0 (which is not what the documentation suggests), then the problem is elsewhere and some earlier operation is not doing what y'all expected.

Re: dbi retieve single col value
by Tux (Canon) on Aug 28, 2008 at 12:59 UTC

    $sth->fetchrow_array () returns what it indicates: a list not a scalar

    If you use bind_columns () (A GOOD CHOICE!), the call should be fetch_arrayref (), not fetch_array ()

    Use UNIQUE or DISTINCT as already suggested if you want just a single value

    or, remember what you saw:

    $dbh->{RaiseError} = 1; my $sth = $dbh->prepare (qq; select tax_id from gene2acc where genomic_ac_ver = '$ref'; ); # qq;; is a nice way to make cut-n-paste to sql easier $sth->execute; my $tax_id; $sth->bind_columns (\$tax_id); my %seen; while ($sth->fetch) { $seen{$tax_id}++ and next; # Only use first occurance print "Entering taxID_format with $tax_id\n"; #taxID_format ($tax_id); } keys %seen or print "No records matched for $ref\nn";

    Enjoy, Have FUN! H.Merijn
      $sth->fetchrow_array () returns what it indicates: a list not a scalar

      ...up to a point. In the case:

      while($array = $sth1->fetchrow_array())

      i.e. in scalar context, Programming the Perl DBI says it will return the contents of the first column.

      However, the documentation http://search.cpan.org/~timb/DBI-1.607/DBI.pm#fetchrow_array is more equivocal:

      If called in a scalar context for a statement handle that has more than one column, it is undefined whether the driver will return the value of the first column or the last. So don't do that. Also, in a scalar context, an undef is returned if there are no more rows or if an error occurred. That undef can't be distinguished from an undef returned because the first field value was NULL. For these reasons you should exercise some caution if you use fetchrow_array in a scalar context.
      This doesn't appear to be the root of the problem. But when faced with an apparently hidden problem, I'm a big believer in clearing away the obviously problematic.

      thats the output.... when I do the same query in mysql with all these ids: pulls out matching records : here the syntax I used on mysql: SELECT tax_id FROM gene2acc where genomic_ac_ver = 'CP000950.1'; here is what I used in the script: SELECT tax_id FROM gene2acc where genomic_ac_ver = '?'; nin foreach loop with CP000950.1 No records matched for CP000950.1 nin foreach loop with CP000950.1 No records matched for CP000950.1 please help me ....got lot of work!
        out put is here...sorry about that: nin foreach loop with CP000720.1 No records matched for CP000720.1 nin foreach loop with CP000950.1 No records matched for CP000950.1 nin foreach loop with CP000950.1