You could give DBIx::FetchLoop a spin....
use DBIx::FetchLoop;
$lph = DBIx::FetchLoop->new($sth, $dbi_method);
$hash_ref = $lph->fetch_current_data;
$rowset = $hash_ref->{previous};
$rowset = $hash_ref->{current};
$rowset = $hash_ref->{next};
$rowset = $lph->fetch_current_row;
$rowset = $lph->previous;
$rowset = $lph->current;
$rowset = $lph->next;
$lph->set_aggregate($new_field, $field);
$lph->reset_aggregate($new_field);
$lph->set_concatenate($new_field, $field);
$lph->reset_concatenate($new_field);
$boolean = $lph->pre_loop($field);
$boolean = $lph->post_loop($field);
$boolean = $lph->pre_loop_substr($field,$offset,$length);
$boolean = $lph->post_loop_substr($field,$offset,$length);
$boolean = $lph->is_first;
$boolean = $lph->is_last;
$count = $lph->count;