Perl DBI - Perl Database Interface

Früher verwendet: Oracle Variante


Überblick

$dbh = DBI->connect(...) Datenbank wählen, mit userid und passwd einloggen
$sth = $dbh->prepare($query)
$sth->execute;
Query ausführen
$sth->bind_columns(...) Spaltenwerte als Variablen verfügbar
$sth->fetchrow_array Datensätze lesen (Schleife)
$sth->finish Ende dieser Query
$dbh->disconnect Verbindung zur DB trennen

Abfrage Kunden

#!/usr/bin/perl

use DBI;

$dbh = DBI->connect('DBI:mysql:j8325200', 'j8325200', '...' );
$sth = $dbh->prepare("select nr, name from kunde");
$sth->execute;
$sth->bind_columns(undef, \$nr, \$name);
while (@row=$sth->fetchrow_array) { print "$nr $name\n"; }
$sth->finish;
$dbh->disconnect;

Was passiert hier?


HTML Kundenliste

Wie vorhin, nur Content-type und HTML Tags zur Listenformatierung dazu, z.B.

...
print "Content-type: text/html\n\n";
...
print "<table>\n";
...
  print "<tr><td>$nr</td><td>$name</td></tr>\n";
...
print "</table>\n";
...

Zum Vergleich: Kundenliste mit Oracle Web Server

Die Prozedur ist hier ein Objekt in der Datenbank, das mit SQL-artiger Syntax angelegt wird und die Oracle-Programmiersprache PL/SQL verwendet:

create or replace procedure listkunde is
cursor c is select nr, name from kunde;
begin
  htp.p('<table><tr><td>Nr<td>Name<td>');
  for i in c loop
    htp.p('<tr><td>' || i.nr || '<td>' || i.name);
  end loop;
  htp.p('</table>');
end;
/
show errors
grant select on kunde to hr;
grant execute on listkunde to hr;
Abspeichern als listkunde.sql (Verzeichnis egal), in Datenbank laden mit sql j8325200 < listkunde.sql
Der URL auf diese Prozedur lautet dann http://miss.wu-wien.ac.at:8889/hr/owa/j8325200.listkunde
wobei Sie natürlich Ihre eigene Matrikelnummer verwenden.
Details im OWS Tutorial

Erfassen

Mit Formular und CGI Modul

use CGI;
$c=new CGI;
$name=$c->param('nr');
$name=$c->param('name');
...
$dbh = DBI->connect('DBI:mysql:j8325200', 'j8325200', '...' );
$sth = $dbh->prepare("insert into kunde values ($nr,\'$name\',...);
...

Achtung: SQL verlangt Hochkommas bei Texten, nicht aber bei Zahlen. Daher \' beim Feld name, nicht aber beim Feld nr.


Beispielformular Kunden Erfassen

<form action=http://miss.wu-wien.ac.at:81/USERCGI/j8325200/kundenerf.pl>
<table>
<tr> <td> Nr:      <td> <input type=text name=nr>
<tr> <td> Name:    <td> <input type=text name=name>
<tr> <td> Adresse: <td> <input type=text name=adresse>
<tr> <td>          <td> <input type=submit value=OK>
</table>
</form>

Ein HTML-Formular, nichts besonderes. Die Prozedur kundenerf.pl folgt auf der nächsten Seite.


Beispielprozedur Kunden Erfassen

#!/usr/bin/perl
use DBI;
use CGI;
$c=new CGI;

$nr=$c->param('nr');
$name=$c->param('name');
$adresse=$c->param('adresse');
$tel=$c->param('tel');

$dbh = DBI->connect('DBI:mysql:j8325200', 'j8325200', '...'
$sth = $dbh->prepare("insert into kunde values ($nr,\'$name\',\'$adresse\',\'$tel\')");
$sth->execute;
print "Content-type: text/html\n\n";
print "OK."

Hochkommas bei name, adresse, tel, nicht aber bei nr.
Warum? Das Feld nr ist vom Datentyp numerisch, die anderen sind Textfelder.


Generator

Für Listenprozeduren, Erfassungformulare und Erfassungsprozeduren mit Daten aus nur einer Tabelle steht ein Generator zur Verfügung:

Userid (zB j8325200):
Name der Tabelle (zB kunde):
Feldnamen, durch Beistrich getrennt (zB nr,name):

Füllen Sie das Formular aus und speichern Sie das Ergebnis mit Hilfe der Zwischenablage in den entsprechenden Dateien:


Table Manager

Der Table Manager

Userid:
Passwd:

Dynamisch generierte Eingabeformulare

Eingaben in Formularen können über Textfelder (input type=text) erfolgen; oft möchte man aber hier die Eingabemöglichkeiten auf zulässige Werte einschränken. Eine Möglichkeit dazu ist die Generierung des gesamten Formularcodes inklusive eines select-Feldes, z.B. um beim Auftrag-Erfassen auf gültige Kundenummern einzuschränken:

use DBI;

print "<form
action=http://balrog.wu-wien.ac.at/usercgi/j8325200/erfauftrag.pl>
Nr: <input type=text name=nr> <br>
Datum: <input type=text name=datum> <br>
Kunde: <select name=kunde>";

$dbh = DBI->connect('DBI:mysql:j8325200','j8325200','j8325200');
$sth = $dbh->prepare("select nr, name from Kunde");
$sth->execute;
$sth->bind_columns(undef,\$nr,\$name);
while (@row = $sth->fetchrow_array) {
  print "<option value=$nr> $name\n";
}

print "</select><br><input type=submit value=OK></form>";

Generierte Eingabeformulare (Forts.)

Die Prozedur erzeugt nun HTML-Code mit einem select-Feld, dessen Optionen die aktuellen Kunden in der DB sind. Die option-Anweisung nimmt als Parameter den value-Wert, der mit den Formulardaten übergeben wird, während der Text nach der option-Anweisung im Pulldown-Menü engezeigt wird.

<form action=...>
...
<select name=kunde>
<option value=10> Meier
<option value=11> Huber
...
</select>
...

Dynamisch zusammengesetzte Links

Ein häufige Aufgabenstellung ist der Verweis von einer Liste auf Details zu jedem Eintrag. So könnte z.B. gewünscht sein, von einer Kundenliste mittels Klick zu Detailinformationen zu einem bestimmten Kunden zu gelangen, etwa welche Aufträge von diesem Kunden bekannt sind. Mit zusammengesetzten Links kann diese Aufgabe gelöst werden. Die Listenprozedur für die Kundenliste wird etwas erweitert:

while (@row = $sth->fetchrow_array) {
  print "$nr $name <a
href=http://balrog.wu-wien.ac.at/usercgi/j8325200/auftrag_kunde?kunde=$nr>
Aufträge </a> <br>\n";
}

Jeder Eintrag enthält nun einen Verweis auf die Folgeprozedur auftrag_kunde, wobei auch eine Parameterübergabe im URL erfolgt (?Name=Wert). In der generierten Liste steht dann z.B.

.../auftrag_kunde?kunde=127>

Sollen mehrere Werte übergeben werden, so wird '&' als Trennzeichen verwendet:

.../folge_proz?kunde=$k&auftrag=$a&datum=$d>

Zusammengesetzte Links (Forts.)

Die Folgeprozedur auftrag_kunde ist eine Listenprozedur (mit Hilfe des Generators einfach erzeugt), in der die select-Anweisung durch eine where-Klausel eingeschränkt ist. Außerdem wird zu Beginn der Prozedur mit Hilfe des CGI-Moduls der Wert des einschränkenden Parameters übernommen:

...
use CGI;
$c = new CGI;
$kunde = $c->param('kunde');
...
$sth->prepare("select nr, datum, kunde from auftrag where kunde = $kunde");

Die zusammengesetzten Links können vielfältig eingesetzt werden, z.B.

Natürlich können auch spezielle Auswertungen verknüpft werden, bei der Artikelliste z.B. für jeden Artikel die Summe der insgesamt abgesetzten Stück, beim Kunden der Gesamtumsatz für den jeweiligen Kunden usw.


Beispiel: Auftraege eines bestimmten Kunden k

Wir holen uns die Kundennummer mit Hilfe des CGI Moduls und schränken damit dann die SQL Abfrage ein:

#!/usr/bin/perl
use DBI;
use CGI;
$cgi = new CGI;
$k = $cgi->param('k');
$dbh = DBI->connect('DBI:mysql:j8325200', 'j8325200', 'j8325200' );
$sth = $dbh->prepare("select nr,datum,kunde from auftrag where kunde = $k");
$sth->execute;
$sth->bind_columns(undef,\$nr,\$datum,\$kunde);
print "Content-type: text/html\n\n<table align=center>\n";
print "<tr><td>nr<td>datum<td>kunde\n";
while (@row=$sth->fetchrow_array) { print "<tr><td>$nr<td>$datum<td>$kunde\n";
}
print "</table>\n";

Der URL könnte z.B lauten http://miss.wu-wien.ac.at:81/USERCGI/j8325200/auftragkunde.pl?k=10
Zum Testen auf der Kommandozeile geben Sie ein: auftragkunde.pl k=10

Offenlegung gem. §25 MedienG