Speichern in array_ref bei DB-Abfrage (perl) [gelöst]

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Speichern in array_ref bei DB-Abfrage (perl) [gelöst]

Beitrag von Duff » 28.09.2006 14:32:22

Hallo,

ich komme nicht so ganz weiter bei einem Ausschnitt aus meinem Perlskript.

Code: Alles auswählen

my $dbh = DBI->connect("dbi:Oracle:$db_name",$db_username,$db_password, \%attr);
my $sql = "select-statement";
my $sth = $dbh->prepare($sql);
$sth->execute();
while(my $z = $sth->fetchrow_arrayref())
{
#       push (@dbstring);
        printf "%8d %-45s %-15s %-50s\n", $z->[0], $z->[1], $z->[2], $z->[3];
}

$sth->finish();
$dbh->disconnect;
Es wird mir zwar aus dem oberen Abschnitt alles aus der Datenbank formatiert ausgegeben, jedoch möchte ich zu diesem Zeitpunkt noch keine Ausgabe vornehmen, sondern alles in einer array_reference speichern. Doch das funktioniert nicht so richtig bei. Bekomme diese dann nicht mehr ausgegeben.

Habe es auch schon mit einem normalen array versucht. Innerhalb der while-Schleife funktioniert ein print. Zu einem späteren Zeitpunkt nicht mehr.
Zuletzt geändert von Duff am 29.09.2006 18:27:00, insgesamt 1-mal geändert.
Oh, yeah!

nepos
Beiträge: 5238
Registriert: 05.01.2005 10:08:12

Beitrag von nepos » 28.09.2006 15:06:45

Hm, ich komme nicht 100% mit, was du machen willst, aber versuchen wirs mal :)
Also, dass dein $z nach der While-Schleife nicht mehr mit nem print zu nutzen ist, ist klar. Der Gueltigkeitsbereich erstreckt sich nur auf die Schleife.
Wenn du alle Ergebnisse auf einmal holen willst, wuerde ich das so machen:

Code: Alles auswählen

my $aref = $sth->fetchall_arrayref();
Dann hast du in $aref alle Zeilen drin. Ganz hilfreich is bei der ganzen Sache immer, Data::Dumper zu nutzen. Damit kann man sich die Struktur von verschachtelten Daten recht gut anzeigen lassen.
Wenn du nun alles aus deiner $aref ausgeben willst, dann so:

Code: Alles auswählen

foreach my $row ( @$aref ) {
  print join(",",@$row),"\n";
}
Ach ja, nur am Rande. Wenn du so ein SELECT nur einmal brauchst, kannst du es auch fixer so schreiben:

Code: Alles auswählen

my $aref = $dbh->selectall_arrayref(qq{SELECT ...},undef,$var1,$var2);
Prepare+Execute sind eigentlich nur dann wirklich wichtig, wenn du ein Statement mit Platzhaltern hast und dieses oefter mit unterschiedlichen Werten aufrufen willst. Manche Datenbanken cachen dieses Statement dann und es bringt dir etwas mehr Performance.

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 28.09.2006 15:16:14

Jo danke.

Das war genau das, was ich gesucht habe.

Die Kurzschreibweise für nur ein Select-Statement

Code: Alles auswählen

my $aref = $dbh->selectall_arrayref(qq{SELECT ...},undef,$var1,$var2);
habe ich aber ehrlich gesagt nicht so ganz verstanden.
Oh, yeah!

nepos
Beiträge: 5238
Registriert: 05.01.2005 10:08:12

Beitrag von nepos » 28.09.2006 15:34:09

Oki, kleines Beispiel: Du hast eine Tabelle mit Daten, die ne Kunden-ID und ein Datum besitzen. Nun willst du alle Daten haben, die von Kunde X und neuer als Datum Y sind:

Code: Alles auswählen

my $aref = $dbh->selectall_arrayref(
  qq{SELECT * FROM tabelle WHERE kunden_id=? AND datum => ? ORDER BY kunden_id ASC, datum DESC},
  undef,
  $X,
  $Y
);
Damit hast du den Vorteil, dass der Datenbanktreiber fuer dich das Quoting erledigt und anderes mehr. Das undef musst du mitgeben, weil viele Befehle an der Stelle eine Hash-Referenz auf spezielle Attribute haben will, die vom benutzten Treiber abhaengen. Das hab ich selbst noch nie gebraucht.

Jetzt klarer?

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 28.09.2006 16:16:02

Ja Dankeschön.

Bin auf jeden Fall wieder einen Schritt weiter.

Bin zur Zeit beim Grübeln, wie ich das obere Beispiel so aufbauen kann, dass die DB-Abfrage in eine Funktion verpackt wird (z.B. get_DBdata { ... }). Ich weiß nur nicht genau, wie ich die Funktion dann aufrufen muss, damit die Ausgabe auch noch funktioniert.
Oh, yeah!

nepos
Beiträge: 5238
Registriert: 05.01.2005 10:08:12

Beitrag von nepos » 28.09.2006 16:45:08

Hm, je nachdem, was du machen willst.
Brauchst du Parameter? Dann eventuell so:

Code: Alles auswählen

sub getData {
  my $dbh = shift;
  my $var1 = shift;
  my $var2 = shift;
  ...
  return $dbh->selectall_arrayref(qq{...}, undef,$var1,$var2, ...);
}
Deine Funktion gibt dir dann die Array-Referenz zurueck, ueber die du wieder auf die Daten zugreifen kannst wie oben beschrieben.

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 29.09.2006 10:25:11

Jo danke.

Aber wie muss ich die Funktion aus dem Programm denn genau aufrufen?
Ich muss doch dann alles in einer Array_Referenz speichern, oder?
Oh, yeah!

nepos
Beiträge: 5238
Registriert: 05.01.2005 10:08:12

Beitrag von nepos » 29.09.2006 11:44:27

Ach so, naja, so z.B.:

Code: Alles auswählen

my $arrayRef = getData($dbh,$var1,$var2);

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 29.09.2006 12:53:48

Irgendwie mach ich was falsch, weil er immer das hier anmeckert:

Code: Alles auswählen

Can't use string ("1") as an ARRAY ref while "strict refs" in use at ./script.pl line 40.
Line 40 ist die foreach-Schleife zur Ausgabe.

Habe das ganze so probiert:

Code: Alles auswählen

sub getData {
        my $dbh = DBI->connect("dbi:Oracle:$db_name",$db_username,$db_password, \%attr);
        my $sql = "select ...";
        my $sth = $dbh->prepare($sql);
        $sth->execute();

        # Alles in einem array_ref ($aref) speichern
        #
        my $aref = $sth->fetchall_arrayref();

        $sth->finish();
        $dbh->disconnect;
}

my $arrayRef = getData();

foreach my $row (@$arrayRef)
{
        print join("\t",@$row),"\n";
}
Oh, yeah!

Benutzeravatar
Duff
Beiträge: 6321
Registriert: 22.03.2005 14:36:03
Wohnort: /home/duff

Beitrag von Duff » 29.09.2006 18:26:39

Ups, habe den "blöden" Fehler von mir gefunden. Hatte in der Funktion das return vergessen.

Code: Alles auswählen

return($aref);
Oh, yeah!

Antworten