PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Perl/Oracle: fetchhash Problem



bionic
12-01-2006, 17:52
Hi,

Ich möchte aus einer Datenbank ein paar ausgewählte Datensätze auslesen und diese als Hash in einem Array speichern.

DB:
Spalte1 Spalte2 Spalte3

Test1A Test1B Test1C

Test2A Test2B Test2C

Test3A Test3B Test3C

Test4A Test4B Test4C

Ein Hash soll nun so aussehen:
%hash1 = (Spalte1 => "Test1A", u.s.w.)

Für jede Zeile soll ein Hash erstellt werden.

Schliesslich sollen die Hash in einem Array zwischengespeichert werden. Also @temp = (%hash1,%hash2,u.sw.)

Dieser Array wird nun durchlaufen und es wird ein neuer Hash gebildet, der NUR Elemente enthält, die in jedem einzelnen %hash von vorhin vorkommen.

Soviel zur Aufgabe... Mein Versuch war nun das ganze mittels Fetchhash abzuholen:

sub get_it {
my $dbh = shift;
my $tabletemp = shift;
my $id = shift;
my %temphash;
my %controlhash;
my @results;

# begin dbaccess
my $sql="SELECT * FROM $tabletemp WHERE ID='$id'";

my $sth = $dbh->prepare($sql) or die $dbh->errstr();
$sth->execute or die $dbh->errstr();
while (%temphash = $sth->fetchhash()){
push @results, \%temphash;
}

$sth->finish ();
# end dbaccess

# begin compare
foreach my %hash (@results){
foreach(keys(%hash)){
if ($hash{$_} eq $controlhash{$_} || !defined $controlhash{$_}){
$controlhash{$_} = $hash{$_};
}
else {
$controlhash{$_} = "";
}
}
}
# end compare

return %controlhash;
}

Ich bin mir ziemlich sicher, dass mein Code oben noch viele kleine Fehler hat. Aber stimmt das Prinzip mit dem speichern der Hashes im Array? Der Datenbankzugriff funktioniert. Leider crashed mir das Skript ohne Fehlermeldung. Er sagt etwas von wegen: "Too many headers".

Hat jemand einen guten Tipp für mich, oder kann mir einen Tipp geben wo suchen?

Vielen Dank!

Molaf
15-01-2006, 08:40
Die Zeile sieht mir verdächtg aus:

push @results, \%temphash;

Ohne den Backslash wird der Hash einfach in ein neues Arrayfeld geschrieben, so sieht es eher so aus als ob Du eine Refferenz darauf übergibst. Da %temphash aber ohnehin nach jedem Schleifendurchlauf verfällt kann das eigentlich nichts werden.

Ich habe nicht genug Zeit das Skript selber zu testen, werde es bei bestehenden Problemen aber gerne die nächsten Tage mal probieren.

mfg Molaf

bionic
16-01-2006, 12:39
So, ich bin ein grosses Stück weitergekommen:


sub get_it {
# generates datacache from tempdb using dbid or from dataimport. dataimport has higher priority.
# if multiple datasets are selected, only the values that are equal are returned.
my $dbh = shift;
my $tabletemp = shift;
my $id = shift;

my $str="";
my %resulthash;
my %controlhash;
my @names;

my $sql="SELECT * FROM $tabletemp WHERE ID='$id'";

my $sth = $dbh->prepare($sql) or die $dbh->errstr();
$sth->execute or die $dbh->errstr();
while (my $hash_ref = $sth->fetchrow_hashref) {
foreach(keys(%{$hash_ref})){
$str .= "push(\@$_,\$hash_ref->{$_});";
push(@names,$_);
}
eval $str;
}

$sth->finish ();

foreach $names(@names){
$controlhash{$names} = "empty";
foreach @poss(eval "\@$names"){
foreach $var($poss){
$controlhash{$names} = $var;
}
}
$resulthash{$names} = $controlhash{$names};
}

return %resulthash;
}

Das gute Ding kann die Daten auslesen und speichert sie im Hash, der Zurückgegeben wird. Natürlich überschreibt er den controlhash jeweils mit dem letzten Wert aus dem Array @$names. Nun möchte ich diese Werte vor dem überschreiben miteinander vergleichen.

Ich habe mir gedacht, dass das so funktionieren könnte:



if ($controlhash{$names} eq "empty" || $controlhash{$names} eq $var){
$controlhash{$names} = $var;
}
else {
$controlhash{$names} = "";
}


Hat jemand eine Idee, wieso das nicht geht?

Vielen Dank!

bionic
16-01-2006, 14:42
Ok... Das Problem ist gelöst:



foreach $var($poss){
if (defined $controlhash{$names} && $controlhash{$names} ne $var){
$controlhash{$names} = "item_locked";
}
else {
$controlhash{$names} = $var;
}
}


;)

Gruss