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

Hi,

I am having problems with the output from a query. I am running perl on Win32, and I am connecting to an MS SQL database using the DBI ODBC driver.

I am doing a query by date. I use bind_columns to work with the results. I use a 'while (fetch())' to write out to a file.

My problem is the first row of my results isn't printed. Everything else prints out just fine. If I dump the array using "print OUTPUT "@rows";" the first row is there, so I know it is coming in my result set.

Is there a limitation on the number of columns I can return? Is there a better way to do this? I am programming and perl newbie.
This is essentially my script:

#!perl use strict; use DBI; my $g_date = '09/23/03'; open (OUTPUT, ">$somefile"); #create a header with column names print OUTPUT "seq,prcdate,frb,account,amount,checknum,tc,disp,run,batc +h,pkt,catcode,deviceid,volid,imagefile,status,typeid,bankId,itemNumbe +r,editStatus,exceptionReasonCode,documentId,postAccount,appCode,bundl +eImageOffset,bundleImageLength,archiveDeviceId,archiveVolId,archiveIm +ageFile,archiveImageOffset,archiveImageLength,userIdAmountEntry,AUX,P +C\n"; my $dbh = DBI ->connect ("DBI:ODBC:mydsn", "user", "password", { Raise +Error => 1, AutoCommit => 0 }); my $sql = "Select * from items where procdate = \'$g_date\' "; my $sth = $dbh->prepare($sql); $sth->execute()or die "\n\n Unable to execute SQL query!\n\n"; my ($seq,$prcdate,$frb,$account,$amount,$check,$tc,$disp,$run,$batch,$ +pkt,$catcode,$deviceid,$volid,$imagefile,$status,$typeid,$bankId,$ite +mNumber,$editStatus,$exceptionReasonCode,$documentId,$postAccount,$ap +pCode,$bundleImageOffset,$bundleImageLength,$archiveDeviceId,$archive +VolId,$archiveImageFile,$archiveImageOffset,$archiveImageLength,$user +IdAmountEntry,$AUX,$PC); my @rows = $sth->fetchrow_array; my $rowcount = @rows; if ($rowcount > 0) # don't do anything when no results { $sth-> bind_columns( undef, \$seq, \$prcdate, \$frb, \$account, + \$amount, \$check, \$tc, \$disp, \$run, \$batch, \$pkt, \$catcode, \ +$deviceid, \$volid, \$imagefile, \$status, \$typeid, \$bankId, \$item +Number, \$editStatus, \$exceptionReasonCode, \$documentId, \$postAcco +unt, \$appCode, \$bundleImageOffset, \$bundleImageLength, \$archiveDe +viceId, \$archiveVolId, \$archiveImageFile, \$archiveImageOffset, \$a +rchiveImageLength, \$userIdAmountEntry, \$AUX, \$PC); while( $sth->fetch() ) { print OUTPUT "$seq,$prcdate,$frb,$account,$amount,$check, +$tc,$disp,$run,$batch,$pkt,$catcode,$deviceid,$volid,$imagefile,$stat +us,$typeid,$bankId,$itemNumber,$editStatus,$exceptionReasonCode,$docu +mentId,$postAccount,$appCode,$bundleImageOffset,$bundleImageLength,$a +rchiveDeviceId,$archiveVolId,$archiveImageFile,$archiveImageOffset,$a +rchiveImageLength,$userIdAmountEntry,$AUX,$PC\n"; } } $dbh->disconnect(); close OUTPUT;

Replies are listed 'Best First'.
Re: ODBC DBI Problems
by ikegami (Patriarch) on Dec 02, 2004 at 19:31 UTC
    my @rows = $sth->fetchrow_array; <--- Reads the first row. You never print it, though. Remove this line. my $rowcount = @rows; <--- Actually, that returns the number of *fields*, since @rows actually contains the first row. Remove this line. if ($rowcount > 0) <--- You can't keep this. You don't even need it. You could reorganize the structure to do something equivalent, but there's no need for that either.

    Also, since RaiseError => 1, checking the return value of method calls is useless, since they'll never return an error. (They'll throw an exception instead.) I turned this off below.

    In your dies, it would be rather useful if you printed the error message.

    You're missing $sth->finish(). I thought disconnect gave a warning if this was missing.

    And finally, there's no reason to not use placeholders instead of inlining the date.

    so:

    my $dbh = DBI->connect( "DBI:ODBC:mydsn", "user", "password", { RaiseError => 0, AutoCommit => 0 } ); my $sql = "Select * from items where procdate = ?"; my $sth = $dbh->prepare($sql); or die "\n\n Unable to prepare SQL query: $DBI::errstr\n\n"; $sth->execute($g_date) or die "\n\n Unable to execute SQL query: $DBI::errstr\n\n"; my ( $seq, $prcdate, $frb, $account, $amount, $check, $tc, $disp, $run, $batch, $pkt, $catcode, $deviceid, $volid, $imagefile, $status, $typeid, $bankId, $itemNumber, $editStatus, $exceptionReasonCode, $documentId, $postAccount, $appCode, $bundleImageOffset, $bundleImageLength, $archiveDeviceId, $archiveVolId, $archiveImageFile, $archiveImageOffset, $archiveImageLength, $userIdAmountEntry, $AUX, $PC ); $sth->bind_columns( undef, \$seq, \$prcdate, \$frb, \$account, \$amount, \$check, \$tc, \$disp, \$run, \$batch, \$pkt, \$catcode, \$deviceid, \$volid, \$imagefile, \$status, \$typeid, \$bankId, \$itemNumber, \$editStatus, \$exceptionReasonCode, \$documentId, \$postAccount, \$appCode, \$bundleImageOffset, \$bundleImageLength, \$archiveDeviceId, \$archiveVolId, \$archiveImageFile, \$archiveImageOffset, \$archiveImageLength, \$userIdAmountEntry, \$AUX, \$PC ) or die "\n\n Unable to bind columns: $DBI::errstr\n\n"; while ($sth->fetch()) { print OUTPUT ( join(',', $seq, $prcdate, $frb, $account, $amount, $check, $tc, $disp, $run, $batch, $pkt, $catcode, $deviceid, $volid, $imagefile, $status, $typeid, $bankId, $itemNumber, $editStatus, $exceptionReasonCode, $documentId, $postAccount, $appCode, $bundleImageOffset, $bundleImageLength, $archiveDeviceId, $archiveVolId, $archiveImageFile, $archiveImageOffset, $archiveImageLength, $userIdAmountEntry, $AUX, $PC ), $/ ); } $sth->finish(); $dbh->disconnect();

    So many variables! Consider not binding anything and optionally use fetch_hashref isntead of fetch:

    my $dbh = DBI->connect( "DBI:ODBC:mydsn", "user", "password", { RaiseError => 0, AutoCommit => 0 } ); my $sql = "Select * from items where procdate = ?"; my $sth = $dbh->prepare($sql); or die "\n\n Unable to prepare SQL query: $DBI::errstr\n\n"; $sth->execute($g_date) or die "\n\n Unable to execute SQL query: $DBI::errstr\n\n"; my $row; print OUTPUT (join(',', @$row), $/) while ($row = $sth->fetch()); $sth->finish(); $dbh->disconnect();
      Thanks, that fixed it!