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

Hi All!

I have created a Perl script which connects to MySQL and fetchs data, the script is large and has many many instances of the section of code below:
my $sql = "SELECT * from shop_items"; my $sth = $dbh->prepare($sql); $sth->execute; while (my $hash_ref = $sth->fetchrow_hashref) { # bla bla bla }

I'm trying to come up with a way of reducing that to just one line, maybe by using a subroutine but Im not sure how, my thinking is along the lines of:
while(my $hash_ref = fetch_data("SELECT * FROM shop_items")) { # bla bla bla } # SUBROUTINE FOR ALL CALLS sub fetch_data { my $sql = @_; my $sth = $dbh->prepare($sql); $sth->execute; }
I'm sure that's not quite right, but you get the drift of my thinking. Is this a good way to get rid of all those sections?

Thanks

Replies are listed 'Best First'.
Re: Clean Up MySQL Code
by Juerd (Abbot) on Apr 20, 2003 at 15:36 UTC

    
    use DBIx::Simple;
    $db = DBIx::Simple->connect(...);
    

    fetchrow_*-ish:

    my $result = $db->query('SELECT * FROM shop_items'); while (my $row = $result->hash) { ... }
    Or, if it is okay to slurp all rows into memory, selectall_*-ish:
    for my $row ($db->query('SELECT * FROM shop_items')->hashes) { ... }

    Note that slurping everything into memory is a bad idea in most cases. The same can be said about SELECT *.

    Juerd
    - http://juerd.nl/
    - spamcollector_perlmonks@juerd.nl (do not use).
    

Re: Clean Up MySQL Code
by DrManhattan (Chaplain) on Apr 20, 2003 at 15:31 UTC
    You can reduce three of your lines to one by using selectall_arrayref() like so:
    my $results = $dbh->selectall_arrayref( "SELECT * FROM shop_items", { Slice => {} } ); foreach my $hash_ref (@$results) { # blah }
    If you want to write it as a subroutine, this would work:
    sub fetch_data { my $dbh = shift; return $dbh->selectall_arrayref( "SELECT * FROM shop_items", { Slice => {} } ); }
    Then you could call it like this:
    foreach my $hash_ref (@{&fetch_data($dbh)}) { # blah }

    -Matt

Re: Clean Up MySQL Code
by astaines (Curate) on Apr 21, 2003 at 09:42 UTC

    Here's a slightly different approach - I create a load of SQL statements, put them in an array,

    foreach my $sql (@sql) { unless ($sth=run_sql($sql)){ die "Failed in processing \"".$sql."\"\n"; } } #Use them like this... my $result = $sth->fetchall_arrayref;

    and then run them using this subroutine -

    # #run_sql # subroutine that does all of the work # sub run_sql{ my $sql = shift; my $sth = $dbh->prepare($sql); if (!$sth) { die "Error:" . $dbh->errstr ." while preparing ".$sql."\n"; } if (!$sth->execute) { die "Error:" . $sth->errstr ." while executing ".$sql."\n"; } return $sth; } # run_sql

    The idea here is that I like to pass statement handles around ($sth), which I can then do whatever I want with. I find this much more flexible than passing result sets around. YMMV!

    Happpy Easter,

    --
    Anthony Staines