Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Sqlite DBI $sth->rows

by The_Jesus (Novice)
on Oct 22, 2003 at 04:17 UTC ( [id://301155]=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to run a query on a sqlite database. After I am through with the query I would like to check the rows. The problem I am having is that $query_handle->rows always returns -1

my $query_handle = $dbh->prepare('SELECT name FROM patient_data WHERE name = ?') or die "Couldn't prepare statement: " . $dbh->errstr;

if ($query_handle->rows == 0) { #DO Something }

What am I doing wrong??? - I am assuming that if the query does not find a name $query_handle->rows would equal 0? I get -1. Thanks in advance.

Replies are listed 'Best First'.
Re: Sqlite DBI $sth->rows
by jeffa (Bishop) on Oct 22, 2003 at 04:49 UTC
    Looks like you are forgetting to call execute after you prepare your handle:
    $query_handle->execute($patient_name);
    I also recommend turning RaiseError on so that you don't have to explicitly call die and use $dbh->errstr. For example:
    use strict; use warnings; use DBI; my $name = shift or die "need patient's name\n"; my $dbh = DBI->connect( 'dbi:SQLite:dbname=foo.dbm',undef,undef, {RaiseError=>1} ); my $sth = $dbh->prepare(' SELECT name FROM patient_data WHERE name = ? '); $sth->execute($name); warn "no match for $name\n" unless $sth->rows;

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Your suggestion about using RaiseError is good. The only snag is that RaiseError does not apply to the connect call that creates the database handle. The success of the connect needs to be checked explicitly.
      my $dbh = DBI->connect('dbi:SQLite:dbname=foo.db',undef,undef, { RaiseError=>1 } ) or die $DBI::errstr;
        ...RaiseError does not apply to the connect call...

        Yes, it does apply. If it doesn't, then it's a bug in the DBD. So you don't need an 'or die ...' on the connect when you use RaiseError

        The success of the connect most certainly does not need to be checked explicitly, that is, by both setting RaiseError and calling die yourself - DBI.pm does it for you:
        
        DBI.pm (version 1.38)
        358: sub connect {
        ...
        416: unless ($dbh = $drh->$connect_meth($dsn, $user, $pass, $attr)) {
                my $msg = "$class->connect($dsn) failed: ".$drh->errstr;
                if (ref $attr) {
                    Carp::croak($msg) if $attr->{RaiseError};
                    Carp::carp ($msg) if $attr->{PrintError};
                }
                DBI->trace_msg("       $msg\n");
                $! = 0; # for the daft people who do DBI->connect(...) || die "$!";
                return undef;
            }
        ...
        

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Sqlite DBI $sth->rows
by lachoy (Parson) on Oct 22, 2003 at 13:09 UTC

    In addition to jeffa's good advice, you cannot rely on rows() returning anything reasonable for a SELECT statement. Don't use it.

    Chris
    M-x auto-bs-mode

      What do you suggest I use in its place?
        Before I give some alternative methods, I thought you might like to get the official explanation on the "rows" method - this is 'perldoc DBI' section on "rows":
        "rows" $rv = $sth->rows; Returns the number of rows affected by the last row affecti +ng com- mand, or -1 if the number of rows is not known or not avail +able. Generally, you can only rely on a row count after a non-"SE +LECT" "execute" (for some specific operations like "UPDATE" and "DELETE"), or after fetching all the rows of a "SELECT" sta +tement. For "SELECT" statements, it is generally not possible to kn +ow how many rows will be returned except by fetching them all. So +me drivers will return the number of rows the application has +fetched so far, but others may return -1 until all rows have been f +etched. So use of the "rows" method or $DBI::rows with "SELECT" sta +tements is not recommended. One alternative method to get a row count for a "SELECT" is + to exe- cute a "SELECT COUNT(*) FROM ..." SQL statement with the sa +me "..." as your query and then fetch the row count from that.
        As the perldocs suggest, here's an example of doing a SELECT COUNT to get the number of rows found:
        my $sql = { SELECT count(*) FROM patient_data WHERE name = ? }; my $sth = $dbh->prepare($sql); $sth->execute($name); my ($count_rows) = $sth->fetchrow_array();
        or, you could fetch all the rows, one-by-one, and count them as you go, like:
        my $sql = { SELECT name FROM patient_data WHERE name = ? }; my $sth = $dbh->prepare($sql); $sth->execute($name); my $count_rows = 0; while (my ($name) = $sth->fetchrow_array()) { ### do something with $name here ### $count_rows += 1; }
        Of course, I haven't done anything with error trapping the DBI statements here, but you definitely should.

        HTH.
        Super Search to the rescue - again.

        I had trouble with this issue, and found a decent thread here SELECT COUNT and DBI: rows that hashed out the issue pretty well with many experienced monks chiming in.

        It looks like the most portable way of doing this is to SELECT COUNT.... before doing the actual SELECT.
        You can also wrap your $sth->fetchrows in a while statement, which is ok if you just want to do nothing when no results are returned. It won't allow you to proactively deal with a situation where 0 records are returned, ie let a user know that their query returned no results.

        hth,
        digger
Re: Sqlite DBI $sth->rows
by JamesNC (Chaplain) on Oct 23, 2003 at 17:03 UTC
    I have to say that even though this is a FAQ, it is a good question, because DBI is unreliable on this one. I have had DBI return rows one time and then return -1 on the exact same query if it was run without disconnecting and reconnecting. I wish I knew enough about the module to help fix this, but apparently it has been like this for a long time. People have reported the issue, it just isn't going to get fixed I suppose :-(

    # I am on Win32- Perl 5.8 - DBI -1.37 DBD::ODBC -1.06
    Here is another one to watch out for
    my $sql = qq( use customers select * from customers );
    If you embed a "USE" inside a complex query and then prepare and execute it via ODBC... you will get zip back and usually an accompanied "Invalid Cursor" message from ODBC. The work-around is to NOT insert a USE statement or to extract the "USE STATMENT" and prepare and execute it SEPERATELY from the rest of the SQL... uggh! You can do this on other platfroms as written, just not via DBI. :-(
    Cheers,
    JamesNC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://301155]
Approved by davido
Front-paged by gmax
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (2)
As of 2024-04-16 23:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found