PERL-Werte (string + xml-Dokument) aus DB speichern [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

PERL-Werte (string + xml-Dokument) aus DB speichern [gelöst]

Beitrag von Duff » 31.10.2006 12:41:28

Hallo,

ich möchte in perl eine Datenbankabfrage speichern.
Und zwar möchte ich aus verschiedenen Tabellen zwei Werte ausgeben lassen. Der erste Wert ist ein String und der zweite Wert ist der Inhalt eines xml-Dokuments.

Habe das ganze versucht mit einer Array-Referenz zu speichern, was aber leider nicht funktioniert.

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();

        my $aref = $sth->fetchall_arrayref();

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

        return ($aref);
}

my $arrayRef = getData();
Zuletzt geändert von Duff am 31.10.2006 14:59:14, insgesamt 1-mal geändert.
Oh, yeah!

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

Beitrag von nepos » 31.10.2006 12:49:55

Was genau funktioniert denn nicht?
Du koenntest mal mit dem Modul Data::Dumper den Inhalt von $aref bzw. $arrayRef anzeigen lassen:

Code: Alles auswählen

use Data::Dumper;
print Dumper($arrayRef);
Damit siehst du ob was drin steht und wenn ja, wie es drinsteht.
Ach ja, wenn du den Select eh nur einmal aufrufst, dann wuerde ich das so machen:

Code: Alles auswählen

sub getData {
  my $dbh = DBI->connect("dbi:Oracle:$db_name",$db_username,$db_password, \%attr)
      or die "Fehler beim Datenbankconnect: $DBI::errstr";

  my $sql = "...";

  # Ohne Platzhalter
  my $aref = $dbh->selectall_arrayref($sql)
      or die "Fehler beim Ausfuehren des Selects: $DBI::errstr";

  # Mit Platzhaltern fuer Parameter - schuetzt gegen SQL-Injection
  #  my $aref = $dbh->selectall_arrayref($sql,undef,$param1, $param2)
  #      or die "Fehler beim Ausfuehren des Selects: $DBI::errstr";

  $dbh->disconnect();

  return $aref;
}
Deine Variante ist auch ok, aber das andere ist kuerzer zu schreiben ;)
Die Sache mit prepare+execute ist vor allem dann gut, wenn du den Select oft ausfuehren willst und nur die Parameter bei jedem Select anpasst.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Re: PERL - Werte (string + xml-Dokument) aus DB speichern

Beitrag von gms » 31.10.2006 13:11:08

Wird "undef" zurückgeliefert und welchen Typ hat das entsprechende Feld ?

Vielleicht liegts daran:

Code: Alles auswählen

LongReadLen (integer, vererbbar)
Dieses Attribut kontrolliert die maximale Länge von 'long' oder 'blob' Feldern, die der Treiber automatisch beim Fangen jeder Zeile von der Datenbank einliest. Ein Wert von '0' bedeutet, daß long Daten nicht automatisch eingelesen werden (fetch sollte undef zurückgeben, wenn LongReadLen 0 ist).
[edit]
Das schöne an @nepos Beispielcode ist die korrekte Fehlerbehandlung :wink:
[/edit]

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

Beitrag von Duff » 31.10.2006 13:38:52

Ok, danke für die Antworten.

Ich bekomme folgende Fehlermeldung zurück:

Code: Alles auswählen

DBD::Oracle::db selectall_arrayref failed: ERROR fetching field 3 of 2. LOB value truncated from 979 to 80. DBI attribute LongReadLen too small and/or LongTruncOk not set at skript.pl line 50.
Undefined subroutine &main::Dumper called at skript.pl line 64.
Also das mit dem Dumper scheint auch nicht so ganz zu funktionieren.
gms hat geschrieben: DBD::Oracle::db selectall_arrayref failed: ERROR fetching field 3 of 2. LOB value truncated from 979 to 80. DBI attribute LongReadLen too small and/or LongTruncOk not set at get_jobinfos.pl line 50.
Undefined subroutine &main::Dumper called at get_jobinfos.pl line 64.
Daran scheint's zu liegen. Nur wie kann man es lösen?
Oh, yeah!

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 31.10.2006 13:44:29

folgende Zeile einfügen und den Wert entsprechend anpassen:

Code: Alles auswählen

$dbh->{LongReadLen} = 1048576;
Gruß
gms

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

Beitrag von nepos » 31.10.2006 13:50:53

Wenn Dumper nicht geht, hast du wohl das

Code: Alles auswählen

use Data::Dumper;
vergessen.

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

Beitrag von Duff » 31.10.2006 13:52:24

Super, danke.

Nun funktioniert's und eine Ausgabe mit

Code: Alles auswählen

print Dumper($arrayRef);
funktioniert auch.

Aber wie werden die einzelnen Paare nun gespeichert?

Spalte1 aus Tabelle ist der erste Wert (string) und Spalte2 aus Tabelle ist der zweite Werte (xml-Dokument)?

Weiß nämlich noch so genau, wie ich die Ausgabe machen soll.
Oh, yeah!

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

Beitrag von nepos » 31.10.2006 14:13:05

Normal sollten das nun Arrays of Arrays sein.
Ausgeben kannst du das so:

Code: Alles auswählen

foreach my $array ( @{$arrayRef} ) {
  print $array->[0], "\t", $array->[1], "\n";
}
Mit Data::Dumper siehst du schoen, wie die Daten geschachtelt abgelegt werden. Drum hatte ich dir das empfohlen ;)

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

Beitrag von Duff » 31.10.2006 14:58:33

Super, danke.

Genauso wie ich es wollte. Funktioniert super.
Danke.
Oh, yeah!

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

Beitrag von Duff » 31.10.2006 15:06:52

Eine Frage hätte ich allerdings noch zu dem Beispiel.

Da ich nicht mit fixen Werten arbeite sondern diese Eingeben will (was auch soweit alles funktioniert), habe ich noch nicht ganz verstanden, was undef in

Code: Alles auswählen

my $aref = $dbh->selectall_arrayref($sql,undef,$param1) or die "Fehler beim Ausfuehren des Selects: $DBI::errstr";
genau bedeutet. Ist das jetzt nur zur Fehleranalyse gut oder sollte man das, auch wenn es funktioniert, trotzdem drin stehen lassen?
Oh, yeah!

Benutzeravatar
goeb
Beiträge: 348
Registriert: 26.08.2006 18:12:08
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von goeb » 31.10.2006 16:47:48

Wenn du mit Platzhaltern im SQL-Statement arbeitest brauchst du das undef, die Parameter für das Statement (in der Sprache der DBI-Doku @bind_values) sind eben der dritte Parameter von selectall_arrayref. Mit dem zweiten Parameter könntest du noch ein paar Sachen an den DBI-Treiber übergeben, brauchst du aber in der Regel nicht, also undef.

Steht auch alles in http://search.cpan.org/~timb/DBI-1.52/DBI.pm, wobei ich zugeben muß daß man sich da manchmal den Wolf sucht wenn man was wissen will :wink:

MfG, goeb

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

Beitrag von nepos » 31.10.2006 16:55:28

Jo, Vorteil der Platzhalter ist vor allem, dass das DBI-Modul das korrekte Quoting uebernimmt und du das nicht haendisch machen musst. Ausserdem wird so auch der Code sauberer ;)

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

Beitrag von Duff » 31.10.2006 16:56:18

Ok, danke für die Ergänzungen...
Oh, yeah!

Antworten