Perl-Programmierung: DBI
Aus Wikibooks
Inhaltsverzeichnis |
[Bearbeiten] Einleitung
Perl besitzt dank des DBI-Moduls[1] und diversen Datenbanktreibern (engl. database drivers, DBD) eine Schnittstelle, um mit verschiedenen Datenbanksystemen arbeiten zu können. Darunter fallen populäre Open-Source-Produkte wie MySQL und PostgreSQL sowie kommerzielle Riesen wie Oracle. Derzeit umfasst dieser Abschnitt die Möglichkeiten der Anbindung an MySQL, PostgreSQL und CSV-Dateien.
[Bearbeiten] MySQL-Zugriff mit DBI
Mit Perl und dem DBI-Modul ist es verhältnismäßig leicht, sich mit einer MySQL-Datenbank zu verbinden und Abfragen abzusetzen. So fern das geeignete Perl-Modul für die Verbindung zu MySQL installiert ist ( DBD::mysql[2] ), kann es auch schon losgehen. Beim Verbindungsaufbau kann man noch allerhand Fein-Tuning betreiben, wie zB mit dem RaiseError- oder dem AutoCommit-Switch. Für weiterführende Erklärungen sollte man die Dokumentation des DBI-Moduls konsultieren. Des Weiteren benötigt man ausreichende SQL-Kenntnisse.
Im Sinne der Sicherheit, Portabilität und Faulheit ist anzumerken, dass es nur von Vorteil ist, die Zugangsdaten in einer externen Datei ( eventuell in Form eines Moduls ) einfach in jedes Script einzubinden, damit, falls sich die Zugangsdaten ändern sollten, der Verwaltungsaufwand gering gehalten wird. Ansonsten müssten die Daten in jedem Script händisch angepasst werden. Außerdem ist in diesem Fall auch die Weitergabe des Quelltextes eher unbedenklich, da die brisante Information in einer separaten Datei steckt. Dieses externe File sollte dann verständlicherweise nicht für jedermann lesbar sein. In folgendem Code-Beispiel wurde jedoch aus Gründen der Einfachheit darauf verzichtet.
[Bearbeiten] Einfaches Beispiel
-
#!/usr/bin/perl
-
use strict;
-
use warnings;
-
use DBI;
-
-
# Deklaration der noetigen Variablen fuer die Verbindung
-
# Falls die Datenbank nicht lokal liegt, muss man zusaetzlich
-
# die Variablen $dbhost und/oder $dbport angeben
-
# my $db_host = "127.0.0.1";
-
# my $db_port = "3306";
-
-
my ($db_user, $db_name, $db_pass) = ("deinuser", "deineDB", "deinpass");
-
-
# Verbindung zur DB herstellen
-
# alternativ ( wenn DB nicht lokal ):
-
# my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port",
-
# "$db_user", "$db_pass");
-
-
my $dbh = DBI->connect("DBI:mysql:database=$db_name", "$db_user", "$db_pass");
-
-
# Vorbereiten des SQL-Statements
-
-
my $query_test = $dbh->prepare("SELECT * FROM deinetabelle");
-
-
# Ausfuehren des Statements
-
-
$query_test->execute() or die $query_test->err_str;
-
-
# Hier koennte weitergehende Verarbeitung erfolgen, eine Auflistung aller Eintraege zB:
-
-
while (my ($col_1, $col_2, $col_3) = $query_test->fetchrow_array) {
-
print "Spalte 1: " . $col_1 . "\n";
-
print "Spalte 2: " . $col_2 . "\n";
-
print "Spalte 3: " . $col_3 . "\n";
-
}
-
-
# Nun erstellen wir doch noch gleich eine neue Tabelle
-
# Statt der Möglichkeit mittels vorherigem prepare und execute, benutzen
-
# wir hier die einfache Methode do
-
-
my $create_query = "CREATE table testtable";
-
-
$dbh->do($create_query);
-
-
# Nachdem alles erledigt ist, schließen wir die Datenbankverbindung
-
-
$dbh->disconnect;
Die eigentliche Arbeit in diesem Script steckt in Zeile 31. Hier wird mittels der Funktion fetchrow_array jeweils eine Zeile in eine Liste/Array eingelesen und zurückgeliefert. Die ersten 3 Werte dieser Liste werden danach den Werten $col_1 bis $col_3 zugewiesen. Sobald fetchrow_array keine Zeile mehr zurückliefert, beendet sich die while-Schleife.
[Bearbeiten] Erweitertes Beispiel mit Modulanbindung
Hier eine von vielen Möglichkeiten die Verbindungsdaten in einem externen File unterzubringen. Der folgende Ansatz bindet die Daten mittels eines Moduls ein.
Das externe File mit den Daten ( ExterneDaten.pm ):
-
#!/usr/bin/perl
-
use strict;
-
use warnings;
-
our @EXPORT_OK = qw($DB_USER $DB_PASSWD $DATABASE);
-
use Exporter;
-
our @ISA = qw(Exporter);
-
-
package ExterneDaten;
-
our $DB_USER = "youruser";
-
our $DB_PASSWD = "yourpasswd";
-
our $DATABASE = "yourDB";
-
-
1;
Dieses File sollte nun mit entsprehend sicheren Zugriffsrechten versehen werden und den Namen ExterneDaten.pm erhalten. Nachdem das erledigt ist, kann man das erste Beispiel auch wie folgt formulieren:
-
#!/usr/bin/perl
-
use strict;
-
use warnings;
-
use DBI;
-
use lib ".";
-
use ExterneDaten;
-
-
# Verbindung zur DB herstellen
-
-
my $dbh = DBI->connect("DBI:mysql:database=$ExterneDaten::DATABASE",
-
"$ExterneDaten::DB_USER", "$ExterneDaten::DB_PASSWD");
-
-
# Vorbereiten des SQL-Statements
-
-
my $query_test = $dbh->prepare("SELECT * FROM deinetabelle");
-
-
# ...
-
# ... alles andere bleibt gleich
-
# ...
Erklärung
In Zeile 5 wird Perl angewiesen das aktuelle Verzeichnis in das @INC-Array aufzunehmen, dies ist notwendig, damit ExterneDaten.pm danach auch, wie in Zeile 6 gefordert, gefunden wird. Durch die package-Anweisung im Modul befinden sich die Variablen im ExterneDaten-Namensraum, weshalb den eigentlichen Variablennamen ExterneDaten:: vorangestellt wird.
[Bearbeiten] DBI-Zugriff auf andere Datenbanksysteme
Im wesentlichen können hier die Erkenntnisse des letzten Kapitels übernommen werden. Den größten Unterschied stellt lediglich die connect-Anweisung dar, die für jedes DBMS etwas anders ausschaut. Des weiteren sollten, um die folgenden Beispiele ausführen zu können, die Module DBD::Pg[3] für PostgreSQL sowie DBD::CSV[4] für CSV installiert sein. Beide Module sind im CPAN zu finden.
[Bearbeiten] PostgreSQL
my $dbh = DBI->connect("DBI:Pg:dbname=$db_name", "$db_user", "$db_pass");
[Bearbeiten] Ein CSV-Verzeichnis
CSV steht für "Comma-separated Values", und bezeichnet keine Datenbank im eigentlichen Sinne, sondern einen Dateityp, eigentlich reine Textdateien im ASCII-Format, die von jedem Texteditor gelesen und bearbeitet werden können. Damit hat der Programmierer die Möglichkeit, SQL zu nutzen, ohne ein DBMS installieren zu müssen. Vorteilhaft, wenn man sparsam mit den Ressourcen umgehen muß.
Als Datenbank verwendet man ein Verzeichnis, und jede CSV-Datei steht für eine Tabelle. Benutzername und Passwort entfallen.
my $dbh = DBI->connect("DBI:CSV:f_dir=/pfad/zu/deinem/csvverzeichnis"); #Oder bei Windows my $dbh = DBI->connect("DBI:CSV:f_dir=c:\\pfad\\zu\\deinem\\csvverzeichnis");
[Bearbeiten] SDBM
SDBM (Standard-Perl-Quelldistribution) ist eine sehr einfache Datenbank, die häufig bei einer gewöhnlichen Linux-Distribution standardmäßig installiert wird. Es werden zwei Dateien erzeugt. Eine mit der Endung .dir und eine .pag, wobei letztere die Daten beinhaltet.
Hier ein erklärendes Beispiel eingebettet in eine Klasse:
package cl_db; use Fcntl; # O_RDWR, O_CREAT, etc. use SDBM_File; sub new # Konstruktor { my $this = shift; my $class = ref($this) || $this; my $self = { temperatur => {}, # Temperaturwerte }; bless $self, $class; # Objekt erzeugen tie(%{$self->{temperatur}}, 'SDBM_File',"temperatur.db", O_RDWR|O_CREAT, 0666); return $self; }
Der Konstruktor verbindet das Hash %self{temperatur} mit der Datenbank (temperatur.db). Es werden im aktuellen Verzeichnis die beiden Dateien temperatur.db.dir und temperatur.dp.pag angelegt bzw. benutzt.
sub writeDB { my $self = shift; my $key = shift; # Datenschluessel my $data = shift; # Datenwert $self->{temperatur}->{$key} = $data; return 1; }
Die Funktion writeDB schreibt Daten in die Datenbank.
sub readDB { my $self = shift; my $key = shift; # Datenschluessel return $self->{temperatur}->{$key}; }
Die Funktion readDB liest bestimmte Daten der Datenbank aus.
sub DESTROY { my $self = shift; untie %{$self->{temperatur}}; } 1; # Returnwert für Package
Der Destruktor löst die Verbindung wieder auf und schließt somit die Datenbank wieder.
Das folgende Beispiel zeigt, wie diese Klasse benutzt werden kann:
#!/usr/bin/perl -w use cl_db; my $db = cl_db->new(); # Konstruktor wird aufgerufen $db->writeDB("InnenTemperatur", 21.0); # Daten schreiben print "Innentemperatur: ", $db->readDB("InnenTemperatur"), "\n"; # Daten lesen

