views:

52

answers:

3

Hi

I am very new to perl (but from a c# background) and I am trying to move some scripts to a windows box. Due to some modules not working easily with windows I have changed the way it connects to the DB. I have an sqlserver DB and I had a loop reading each row in a table, and then within this loop another query was sent to select different info. I was the error where two statements can't be executed at once within the same connection. As my connection object is global I couldn't see an easy way round this, so decided to store the first set of data in an array using:

my $query = shift;
    my $aryref = $dbh->selectall_arrayref($query) || die "Could not select to array\n";
    return($aryref);

(this is in a module file that is called)

I then do a foreach loop (where @$s_study is the $aryref returned above)

  foreach my $r_study ( @$s_study ) {
    ~~~             
    my $surveyId=$r_study->{surveyid};  <-------error this line
 ~~~~               
        };

When I run this I get an error "Not a hash reference". I don't understand?! Can anyone help!

Bex

+1  A: 

$r_study->{surveyid} is a hashref

$r_study->[0] is an arrayref

this is your error. You should use the second one

benzebuth
Ah.. is there anyway I can query the columns by name? I need the "data set" offline ...
Bex
@Ben, you should be able to call `selectall_hashref` if you want a hashref. Check out the full docs here: http://search.cpan.org/~timb/DBI/DBI.pm#selectall_hashref
dsolimano
selectall_hashref returns a hash ref of hash refs. Bex wants an array ref of hash refs. So selectall_arrayref is the right way to go - but with the addition of { Slice => {} }.
davorg
+4  A: 

You need to provide the { Slice => {} } parameter to selectall_arrayref if you want each row to be stored as a hash:

my $aryref = $dbh->selectall_arrayref($query, { Slice => {} })

See perldoc DBI for more details.

eugene y
I tried this the first time but removed it as I thought this was causing the error.. I think benzebuth below may have it?
Bex
A: 

If you have a problem with a method, then a good first step is to read the documentation for that method. Here's a link to the documentation for selectall_arrayref. It says:

This utility method combines "prepare", "execute" and "fetchall_arrayref" into a single call. It returns a reference to an array containing a reference to an array (or hash, see below) for each row of data fetched.

So the default behaviour is to return a reference to an array which contains an array reference for each row. That explains your error. You're getting an array reference and you're trying to treat it as a hash reference. I'm not sure that the error could be much clearer.

There is, however, that interesting bit where it says "or hash, see below". Reading on, we find:

You may often want to fetch an array of rows where each row is stored as a hash. That can be done simple using:

my $emps = $dbh->selectall_arrayref(
    "SELECT ename FROM emp ORDER BY ename",
    { Slice => {} }
);
foreach my $emp ( @$emps ) {
    print "Employee: $emp->{ename}\n";
}

So you have two options. Either switch your code to use an array ref rather than a hash ref. Or add the "{ Slice => {} }" option to the call, which will return a hash ref.

The documentation is clear. It's well worth reading it.

davorg
Davorg.. that is the exact article I was reading.. I have done as your second example shows and that's when I am getting the error "Not Hash Reference". It's the whole concept of "hashes" that I don't really understand.. nor why the example isn't working for me! Ps.. I did have the slice in it to start.. but removed it as found conflicting documentation.. either way didn't work!
Bex
Ok. I suspect that we might be going in completely the wrong direction here. I assume that the code was working (with Slice => {}) before you moved the application to Windows. So I wonder if the problem is that your Windows box has an older version of DBI which doesn't support that syntax. Can you try running "perl -MDBI -le'print $DBI::VERSION'" on both of the systems to report what versions of DBI you have installed. You might need to update the version of DBI on your Windows system.
davorg
I've just checked the changelog (http://search.cpan.org/~timb/DBI/Changes) and the Slice => {} syntax was added in DBI version 1.20 which was released in 2001. I really hope you're not using a version that is that old :-)
davorg
in the file it says I am running v 1.6.15 (im not sure where you mean run the other bit?) - this method wasn't on the old box, it was using DBD::sybase to connect to the db, but I couldn't get the client libraries, so I changed it to using straight DBI with a DSN to connect to Sql server, but I have nested queries and I was getting the error:Connection is busy with results for another hstmt (SQL-HY000) .... tried adding the odbc_cursortype => 2 but it didn't fix it, that;s why I changed it to try using an array. I don't mind which error can be fixed, but so far I'm stumped with both!
Bex