Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Weird DBI/Array Use

by madhatter (Sexton)
on Jan 08, 2001 at 01:11 UTC ( #50387=perlquestion: print w/replies, xml ) Need Help??

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

I'm trying to run all my DBI calls through a subroutine:
sub db_execute { my(@return,@a,$cursor); unless($VARS{connected}){db_connect();$VARS{connected}++;} undef @return; $cursor = $dbh->prepare($_[0]); $cursor->execute || db_error(); unless($_[1]){ while (@a = $cursor->fetchrow){push (@return,@a)} return (@return); } }
The idea is to get it to automatically handle the errors. The connect and error subs work.

What I want to do is push to @return a reference (I think) to @a, so later I can call something along the lines of:

my $SQL = "select a,b,c from table"; my @lines = db_execute($SQL); while( ($a,$b,$c) = @lines ){ .. }
What changes do I have to make above to get this to work?


Replies are listed 'Best First'.
Re: Weird DBI/Array Use
by salvadors (Pilgrim) on Jan 08, 2001 at 01:28 UTC

    Rather than rolling your own version of this, perhaps you could use $dbh->selectall_arrayref instead?

    Then you can do something like:

    sub db_execute { ... return $dbh->selectall_arrayref($query); } my $result = db_execute($SQL); foreach my $row (@$result) { my ($a, $b, $c) = @row; ... }

    Note that this way you can also skip the 'prepare' stage you're doing, as it seems pretty pointless the way you're doing it (you're not gaining any of the benefit of preparing frequently-used queries by doing it inside this sub). However, if you move the 'prepare' elsewhere, and pass this subroutine a prepared query instead, selectall_arrayref will still handle this just fine.


Re: Weird DBI/Array Use
by chipmunk (Parson) on Jan 08, 2001 at 01:24 UTC
    How about:
    sub db_execute { my(@return, @a, $cursor); unless ($VARS{connected}) {db_connect(); $VARS{connected}++;} $cursor = $dbh->prepare($_[0]) || db_error(); $cursor->execute || db_error(); unless ($_[1]) { return @{ $cursor->fetchall_arrayref }; } } my $SQL = "select a, b, c from my_table"; my @rows = db_execute($SQL); for (@rows) { my @row = @$_; ... }
    (I'm not sure what the unless($_[1]) is for...)

    Update: Use fetchall_arrayref() instead of looping over fetchrow().

Re: Weird DBI/Array Use
by madhatter (Sexton) on Jan 08, 2001 at 03:29 UTC
    If I know that my query is going to return only one entry, how do I avoid using a loop to gather the returned data? Anything I try just returns me an array reference.
    my $result = db_execute($SQL); foreach(@$result){ my ($title,$body) = @$_; print $title; }
      If you have an array reference that you "know" will only contain one item, then it sounds like you just want to access the first element of the array:
      my $result = db_execute($SQL)->[0]; my ($title, $body) = @{$result}; # or my ($title, $body) = @{db_execute($SQL)->[0]};
      Check out perlref, perllol and especially perldsc for information about references and the ways you can use them.
      If you only want one row then do use
      my @result = $dbh->selectrow_array("SELECT MAX(foo) FROM blah");

      If you just want one column then
      my @rows = @{ $dbh->selectcol_arrayref("SELECT id FROM blah") };

      Otherwise do a full $dbh->selectall_arrayref as salvadors suggests or use the full prepare, execute, fetchrow syntaxes like you were doing originally.

      For information on these syntaxes and more read up on the DBI docs.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://50387]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2022-01-22 09:28 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (62 votes). Check out past polls.