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

I've never used DBI before. So I am doing something wrong here but I can't find it. Using sqlplus I get a return of about 200 rows. Using this script I get a return of 1?? The only thing I can think is that I am processing the query output incorrectly because the script seems to be taking the same amount of time running the query as sqlplus does.

-- snip --

$dbh = &ora_login($DB,$UN,$PW) or die("Oracle login FAILED."); $sql = "select distinct(clli) from gvc_traffic30"; $cursor = &ora_open($dbh,$sql) or die("Failed query (bad query?). $!\n +"); @MYARRAY= &ora_fetch($cursor) or die("Failed to get return from query. + $!\n"); foreach my $clli ( @MYARRAY ) { chomp($clli); $c++; if ( /\W/ ) { print "Found bad character in line $c."; } else { print "This clli appears to be OK."; } print " : $clli\n"; }

-- !snip --

The script is supposed to grab a list of items from the database that have either been stored properly or have been stored with improper characters in them. I will eventually get to fixing that but for now I am using my problem as a way or learning DBI. I am only concerned with seeing the data in the table for now (plus of course sorting each row out with non-alphanumerics in them).

I have tried for loops, foreach loops (above), and while loops (of course didn't work)...none of which seem to work so I can only assume that I am not getting the proper data into the proper data type somehow... ???

My current output is:

$ perl traffic.pl Use of uninitialized value in pattern match (m//) at traffic.pl line 3 +6. Use of uninitialized value in concatenation (.) at traffic.pl line 41. This clli appears to be OK. : $

Suggestions would be very much appreciated.

----------
- Jim

Edit: chipmunk 2001-08-20

Replies are listed 'Best First'.
Re: Using Oraperl for the first time... (was: Using DBI for the first time...)
by chromatic (Archbishop) on Aug 21, 2001 at 08:09 UTC
    In list context, ora_fetch() returns an array, one element per field. It does not return all rows. You'll have to call it in a while loop for that. See Oraperl for more details, 'cuz the error checking isn't that great.

    (Of course, Oraperl is, more or less, backwards compatibility for perl 4 scripts. It's probably better to bite the bullet and move to DBI for new programs.)

      Wow! So, if there are 300 rows each with only one element per and that particular column isn't indexed then potentially I could be doing 300 full table scans to get the information I want using Oraperl? That will take absolutely forever! Is using DBI going to alleviate that possibility?
      How did people get along with this back in the day?!?! :)

      ----------
      - Jim

Re: Using DBI for the first time...
by snafu (Chaplain) on Aug 21, 2001 at 01:37 UTC
    Just a quick note to everyone. I have been chatting with some folks in the PM and it looks like there maybe some information I left out (purposefully) that maybe needed. Therefore, here it is...the whole script:

    #!/usr/bin/perl -w use strict; use DBI; use Oraperl; use Env; my $DB = "DBNAME"; my $UN = "USERNAME"; my $PW = "PASSWORD"; my ($dbh,$sql,$c,$cursor,@MYARRAY,$numElements); $dbh = &ora_login($DB,$UN,$PW) or die("Oracle login FAILED."); $sql = "select distinct(clli) from gvc_traffic30"; $cursor = &ora_open($dbh,$sql) or die("Failed query (bad query?). $!\n +"); @MYARRAY= &ora_fetch($cursor) or die("Failed to get return from query. + $!\n"); foreach my $clli ( @MYARRAY ) { chomp($clli); sleep(5); $c++; if ( /\W/ ) { print "Found bad character in line $c."; } else { print "This clli appears to be OK."; } print " : $clli\n"; }

    Perhaps the Oraperl.pm is not widely used?

    ----------
    - Jim

      Just to illustrate I have rewritten your script to use DBI.
      Note that I don't have access to Oracle so I haven't tested it.

      The rewrite is quite simple:

      #!/usr/bin/perl -w use strict; use DBI; use Env; my $DB = "DBNAME"; my $UN = "USERNAME"; my $PW = "PASSWORD"; my ($dbh,$sth,$clli,$c); $dbh = DBI->connect("dbi:Oravel:$DB",$UN,$PW, {AutoCommit => 0, RaiseError => 1) or die("Oracle login FAILED, $DBI::errstr"); $sth = $dbh->prepare("select distinct(clli) from gvc_traffic30"); $sth->execute; $sth->bind_col(1, \$clli); while ($sth->fetchrow_arrayref ) { $c++; if ($clli =~ /\W/ ) { print "Found bad character in line $c."; } else { print "This clli appears to be OK."; } print " : $clli\n"; }
      Note that I don't do any error checking. This is because I set $dbh->{RaiseError} in the connect call, so the DBI will do all neccessary errorchecking for me!

      Check the DBI documentation to see what this does.

      Happy DBI'ing

        Aside from a couple of typos your code worked great. I appreciate it. Now I shall sit back and study it.

        NOTE: Typos were on lines 12 & 13.

        Im not sure if Oravel is what you wanted since I have not checked the DBI docs yet but I changed it to Oracle (knowing that that is a proper driver for DBI) and it worked
        Original
        $dbh = DBI->connect("dbi:Oravel:$DB",$UN,$PW,
        Changed
        $dbh = DBI->connect("dbi:Oracle:$DB",$UN,$PW,

        This next one was simply a case of a missing bracket.
        Original
        (...{AutoCommit => 0, RaiseError => 1) or
        Changed
        (...{AutoCommit => 0, RaiseError => 1}) or

        This is really great! Thanks for the example work.

        ----------
        - Jim

Re: Using DBI for the first time...
by VSarkiss (Monsignor) on Aug 21, 2001 at 01:33 UTC

    Uhm, you're still not using DBI. This looks like oraperl or something similar. You can't miss DBI programs because right up at the top they say: use DBI;usually followed by something like: use DBD::Oracle;        # for exampleWithout knowing what ora_fetch does, it's pretty much impossible to say what may be going wrong.

      It turns out that putting use DBD::Oracle at the top of the script is usually unnecessary. The DBI module will load the appropriate DBD module itself based on your connect string, e.g. $dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd);.

      Although there's no harm in loading DBD::Oracle explicitly, you only really have to do it when you want to use Oracle's type constants: use DBD::Oracle qw(:ora_types);