Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hi,
I am using DBI library to connect to Oracle dB. I am using fetchrow_hashref() function to retrive data from a select query
The problem I have is the order of the columns in the select query. It is not the same as what I give in the select statement
For eg, suppose I have select e1,e2,e3,e4 from emp;
I get the order of the columns as e1,e4,e3,e2
How do I ensure that I get the same order in the resultset as I define in the select query
Re: Select quuery result sets
by pajout (Curate) on Aug 23, 2010 at 09:11 UTC
|
fetchrow_hashref returns hashref. That referenced hash (like as every hash) has not defined order. This is just set of key-value pairs.
If you want to obtain db data in specified order, use fetchrow_arrayref() or similar functions. | [reply] |
Re: Select quuery result sets
by codeacrobat (Chaplain) on Aug 23, 2010 at 09:46 UTC
|
Use a hashslice when you need the values in proper order.
my @keys=qw(e1 e2 e3 e4);
...
my $result_href = $sth->fetchrow_hashref ...
my @values = @{$result_href}{@keys};
If you just want to dump the hash have it sorted, try Data::Dump. Data::Dumper also produces sorted output, when $Data::Dumper::Sortkeys=1; is set.
print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});
| [reply] [d/l] [select] |
Re: Select quuery result sets
by sundialsvc4 (Abbot) on Aug 23, 2010 at 12:56 UTC
|
By definition, the keys in a hash are unordered.
If you need to work with columns in a particular order, simply create a separate array-variable containing the column names in the order that you need. (Construct this array in the same logic that is building the SELECT statement.) Then, iterate through that array to get each successive column-name, and use that column-name to fetch the data from the hash.
Notice that the order of the columns in the SELECT statement will no longer matter: the only thing that matters is the order of the names in the array.
In the spirit of creating robust, reliable, self-diagnosing code, you should verify that every column-name you’re looking for does, in fact, exist in the row-data hashref. It would be an extremely easy thing to make a “tpyo” here, with the consequence that a column of data would never show up in the output... and, maybe, no one would immediately notice the bug. The code should assert that every single column-name must exist (even if the value is NULL), and, IMHO, should die if it does not.
| [reply] |
Re: Select quuery result sets
by Anonymous Monk on Aug 23, 2010 at 12:08 UTC
|
Hello Monks,
Thank you for the reply. The reason for not using fetchrow->arrayref is we require the column names as well We need to pass the entire resultset (Column names & column values) to a hash which prints it to the file. The extract from the script is given below
$stmt = $dbh->prepare("$sql17");
$stmt->execute();
if($DBI::errstr)
{
warn "Execution of SQL failed: $DBI::errstr\n";
$dbh->rollback;
closeOracleConnection($dbh);
}
else
@rowData = $stmt->fetchrow_array();
$rowcnt = $#rowData;
for ($i = 0; $i < $rowcnt; $i++) {
@rs = $stmt->fetchrow_hashref();
push(@retArray,@rs);
}
$stmt->finish;
if ($#retArray == -1) {
print (stdout "\nCould not generate values\n");
exit (-1);
}
Need your valuable inputs to resolve this
| [reply] [d/l] |
|
I am not sure, what output data structure you require. Please, can you specify it?
| [reply] |
Re: Select quuery result sets
by Anonymous Monk on Aug 25, 2010 at 17:14 UTC
|
| [reply] |
|
Hence my suggestion, above, that the simplest approach is simply to remove any assumptions (hence, dependencies) upon the order of the field-names in the query. Since you have full control over the entire procedure, simply deal with the two problems separately. The SELECT statement only need make sure that the necessary columns are returned. Build a separate (Perl) list containing the column-names in the order that you need to present them. Then, iterate through that list. Problem (neatly) solved.
| [reply] |
Re: Select quuery result sets
by petecm99 (Pilgrim) on Aug 26, 2010 at 12:18 UTC
|
You should be able to reference them as individual fields, like so:
$emp_qry->execute();
while ( my $emprec = $emp_qry->fetchrow_hashref ) {
$tmp_e1 = $emprec->{e1};
$tmp_e2 = $emprec->{e2};
$tmp_e3 = $emprec->{e3};
$tmp_e4 = $emprec->{e4};
}
$emp_qry->finish();
Hope this helps...
| [reply] [d/l] |
|
|