| Perl-Basics | Perl-Enhanced | ||
|---|---|---|---|
Tips und Tricks zu Perl
MySql-Datenbankzugriff via DBI
Da im Forum von perl-community.de häufig Fragen zum Zugriff mit Perl ueber DBI und DBD::mysql kommen, versuche ich hier die wichtigsten Grundregeln zu erklären.
(Bei den folgenden Code-Beispielen gehe ich davon aus, daß der Server myserver, die Datenbank mydb, der zugreifende Benutzer myuser heißt und das Passwort geheim.)
- Von wo bekomme ich Informationen zu DBI und mysql?
- Perl-Moduldokumentation auf CPAN: DBI und DBI::mysql
- oder einfach: perldoc DBI, perdoc DBI::FAQ oder perldoc DBD::mysql an der Shell eingeben.
- oder in Büchern wie z.B. Programmierung
mit Perl::DBI,
MySQL - new technology . Mit einem Vorwort von Michael "Monty" Widenius
- Wie stelle ich eine Verbindung zur Datenbank auf meinem MySql-Server
her?
#! /usr/bin/perl use warnings; use strict; use DBI; # laden des DBI-Moduls my $dsn = 'DBI:mysql:mydb:myserver'; # datasourcename: wenn myserver weggelassen wird, # wird standardmäßig localhost verwendet. my $attributes = { PrintError => 0, RaiseError => 0 }; # siehe Doku zu DBI my $dbh = DBI->connect($dsn, 'myuser', 'geheim', $attributes) or &WriteError('', "Error in connecting to $dsn", die => 1); # immer Returncodes und Fehler auswerten!!! # --- Fehlerbehandlungsroutine sub WriteError { my ($dbh, $message, %action) = @_; if( $action{die} ) { die "$message:\n $DBI::err ($DBI::errstr)\n"; } else { warn "$message:\n $DBI::err ($DBI::errstr)\n"; } # bei CGI-Scripten sollte man wahrscheinlich die...; durch print ...; exit; # ersetzen, und warn...; durch ein normales print ... ohne exit, weil bei # den meisten Webservern ein 500er Fehler kommt, wenn das Script Text auf STDERR # ausgibt und das Webserver-Log zugemüllt wird. Als Alternative kann man für die # Entwicklung noch folgende Zeile einfügen: # use CGI::Carp qw(fatalsToBrowser warningsToBrowser); } # WriteError - Wie trenne ich die Verbindung ordnungsgemäß?
$dbh->disconnect();
- Wie führe ich ein INSERT-Statement aus?
Beim Ausführen eines SQL-Insert-Statements gibt es folgende Probleme:
- SQL-Sonderzeichen müssen escaped werden.
- Ein Wert für eine Spalte darf nicht für die Datenbankspalte zu lang sein.
- Eventuelle Fehlermeldungen müssen abgefragt/ausgewertet werden.
Als Beispieltabelle nehme ich folgende Tabelle für ein Mini-Gästebuch:
# Datenbanktabelle: guestbook (id, date, name, nachricht) # id: INTEGER UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY # date: TIMESTAMP # name: VARCHAR(32) # nachricht: TINYTEXT # id ist der Primärschlüssel der Datenbank; er kann die Werte eines # vorzeichenlosen Integerwertes annehmen, also Zahlen von 0-65535. Durch # AUTO_INCREMENT ist id ein Zähler, der sich automatisch bei jedem INSERT # um 1 erhöht. # date: ist ein Datum der Form: yyyymmddhhmmss. Dieses Feld hat bei MySql # einen Standardwert. Wenn also kein Wert (oder NULL) in diese Spalte eingefügt # wird, dann wird das aktuelle Systemdatum verwendet. Dies hat den Vorteil, daß # man das Systemdatum nicht in Perl ermitteln muß. # name: dieses Feld kann beliebige ASCII-Zeichen aufnehmen, und zwar maximal 32. # nachricht: dieses Feld kann beliebige ASCII-Zeichen aufnehmen, und zwar maximal 255 .Stimmt das? my $table = "guestbook"; my $name = "Strat"; my $message = "Hallo Strat, jetzt schreibe ich auch mal 'ne Nachricht.\nGruss Martin\n"; # Verbindung zur Datenbank erstellen wie in Punkt 2 angegeben. $name = $dbh->quote($name); # 4.1. $message = $dbh->quote($message); # 4.1. if (length($name) > 31) { # 4.2. # Fehler oder Abschneiden } if (length($message) > 255) { # 4.2. # Fehler oder Abschneiden } # SQL-Statement erzeugen. Durch das $dbh->quote sind schon um $name und $message # einfache Hochkommatas herum, sodaß wir sie hier nicht mehr angeben brauchen. my $statement = "INSERT INTO $table (name, message) VALUES ($name, $message); # SQL-Statement ausführen: unless ($dbh->do($statement)) { &WriteError($dbh, "Error in executing Sql-Statement:\n\t$statement"); } else { # Daten wurden erfolgreich eingefügt. } # Verbindung trennen, wie in Punkt 3. angegeben.
- Wie führe ich ein SELECT aus?
# Verbindung zur Datenbank erstellen wie in Punkt 2 angegeben my $statement = "SELECT * FROM guestbook WHERE name = 'Strat' "; my $sth = $dbh->prepare($statement); unless ($sth) { # Fehlerabfrage &WriteError($dbh, "Error in preparing SQL:\n\t$statement"); } $sth->execute() or &WriteError($dbh, "Error in executing SQL:\n\t$statement"); while ( my $result = $sth->fetchrow_hashref() ) { foreach my $name (sort keys %$result) { print "$name => $result->{$name}\t"; } # foreach print "\n"; } # while $sth->finish(); # statement handle wieder freigebenOft wird in Beispielen anstelle von fetchrow_hashref() oder fetchrow_arrayref() nur fetchrow() verwendet, z.B.
while (my ($value1, $value2) = $sth->fetchrow() ) {was eine große Schwäche hat. Was passiert nämlich, wenn sowohl $value1 als auch $value2 in der Datenbank NULL sind? Dann werden sie in Perl zu undef, und die while-Schleife bricht ab, obwohl vielleicht noch nicht alle Daten ausgelesen worden sind.
- Wird fortgesetzt...
Letztes Update dieser Seite: Tuesday, 27-Jun-2006 20:37:01 CEST