Datenbanken unter Linux - ein Einstieg - free

Werbung
Datenbanken unter Linux — ein Einstieg
Carsten Zerbst
13. Juni 2001
Möchte man Daten, wie zum Beispiel Adressen, Rechnungen oder die Videosammlung verwalten, bieten sich Datenbanken an. Dieser Artikel soll einen
Einstieg in das Arbeiten mit Datenbanken unter Linux geben. Nach einer
Einführung wird die Installation von PostgreSQL beschrieben. Daraufhin werden die Möglichkeiten zur Strukturierung von Daten, ihre Eingabe und Abfrage erläutert. Zum Schluß werden die verschiedenen Möglichkeiten zur Kopplung von externen Programmen mit der Datenbank vorgestellt.
1
Was ist eine Datenbank ?
Hinter dem Schlagwort Datenbank verbergen sich
verschiedene Komponenten. Dies ist zum einen das
Datenbank-Management-System (DBMS), das heißt die
Software, welche die Daten verwaltet. Unter Linux sind
diese beispielsweise PostgreSQL, MySQL, Adabas oder
Oracle. Die Datenbank bezeichnet eigentlich den Bestand der Daten, der durch das DBMS verwaltet wird.
Das Datenbanksystem (DBS) ist die Gesamtheit aus
DBMS und Datenbank.
den auch als Relationen bezeichnet, was den Systemen
auch den Namen relationale DBMS einbringt. Die Tabellen bestehen aus einzelnen Spalten oder Attributen, in denen jeweils nur Daten eines Datentyps gespeichert werden können. Die Zeilen der Tabelle enthalten die Daten
oder Tupel. Der Aufbau der Tabellen wird auch als Datenbankschema bezeichnet.
Relationenname
Attribute
Mitglieder
Id
Name
1
2
3
Aufgabe eines DBS ist die dauerhafte Verwaltung von
großen Datenmengen. Damit das Ganze reibungslos
abläuft, werden einige Anforderungen an das DBS gestellt:
Mustermann
Musterfrau
Musterstudent
Vorname
Geburtstag
Hans
Hanna
Hanno
23.04.1956
02.11.1945
11.07.1968
...
Tupel
Relation
Atomarität Es muß möglich sein, eine Anzahl von
Änderungen zu einer Einheit zusammenzufassen. Das
DBMS muß gewährleisten, daß alle Änderungen erfolgreich bearbeitet oder verworfen werden. Wenn ein Fehler
auftritt, muß der Zustand vor der ersten Änderung wiederhergestellt werden.
Integrität Die Daten müssen integer sein. So darf es keine Rechnungen ohne Kunden geben oder fünf verschiedene Schreibweisen einer Person. Dieses Integrität muß
immer gewährleistet sein; auch eine Fehlbedienung oder
ein Stromausfall darf daran nichts ändern.
Isolation Änderungen an einem Datensatz dürfen keine
ungewünschten Nebenwirkungen auf andere Datensätze
haben.
Persistenz Alle Daten müssen persistent (dauerhaft) gespeichert sein.
Bei den heute üblichen DBMS werden die Daten in tabellenähnlichen Gebilden gespeichert. Diese Tabellen wer-
2
Die Datenbanksprache
Bei relationalen DBMS werden alle Operationen mit Hilfe einer speziellen Sprache, der Standard Query Language (SQL, manchmal auch Sequel ausgesprochen), durchgeführt. Die Sprache verfügt über eine Reihe von Kommandos oder Statements. Mit ihr lassen sich die Tabellen
definieren und ändern, Daten behandeln, aber auch die
Benutzerverwaltung durchführen. Für SQL gibt es mehrere ISO-Standards, die allerdings unterschiedlich weit
von den DBMS unterstützt werden. Die meisten DBMS
bringen außerdem eigene Erweiterungen mit, die nicht
auf anderen Systemen funktionieren. Die weiter unten
vorgestellten Statements gehören zum Umfang von SQL92 und laufen unter den meisten freien Systemen, die
Ausnahmen sind extra gekennzeichnet. Es handelt sich
bei SQL nicht um eine selbstständige Programmiersprache, sie wird über ein Abfragewerkzeug oder eingebettet
in Sprachen wie Tcl, Perl oder C verwendet.
Beispiel Vereinsverwaltung
Für einen Verein soll eine Mitgliederverwaltung erstellt werden. Es sind für 1500 persönliche und korporative Mitglieder die Daten zu verwalten. Die Daten umfassen im einzelnen die persönlichen Daten
der Mitglieder wie Name und Vorname, bis zu drei
Adressen pro Mitglied sowie die Beitragsrechnung.
Neben der reinen Verwaltung der Daten soll auch die
Möglichkeit gegeben sein, Serienbriefe und Beitragsrechnungen zu erstellen.
3
nen ist schon ein Nutzer postgres eingerichtet. Unter diesem Unix-User laufen dann alle Prozesse, die zur
Datenbank gehören. Die Daten von PostgreSQL werden in einem beliebigen Verzeichniss gespeicher, z.B.
/usr/local/pgsql/data. Hat man Postgresql selber kompiliert, muß dieses Verzeichnis muß dem Nutzer
postgresql gehören und initialisiert werden:
# mkdir -p /usr/local/pgsql/data
# chown postgresql /usr/local/pgsq/data
# su postgresql
> /usr/local/pgsql/bin/initdb
➥ -D /usr/local/pgsql/data
Installation einer Datenbank
Bevor man die erste Zeile SQL schreibt, braucht man zuerst ein lauffähiges DBMS. Aus der Vielzahl der in Frage kommenden DBMS wurde hier PostgreSQL gewählt.
Von den klassischen freien DBMS unterstützt es die meisten SQL Statements, außerdem bietet es viele Schnittstellen, um es leicht mit anderen Programmen zu verknüpfen. Eine weitere beliebte Datenbank ist MySQL
[8]. Dieses DBMS ist bei einfachen Operationen schneller, unterstützt dafür aber weniger SQL Statements. Ein
Vergleich zwischen MySQL und PostgreSQL findet sich
zum Beispiel in [9].
Die Quellen von PostgreSQL können von [2] bezogen
werden, viele Distributionen bieten es auch als fertig
zum Installieren an. Wählt man die Quelltextform, muß
das DBMS erst kompiliert werden.1 Zur Installation von
PostgreSQL sind folgende Schritte durchzuführen:
#
#
#
#
cd /usr/local/
tar -xzf postgresql-7.0.3.tar.gz
cd PostgreSQL-7.0.3/src/
./configure --prefix=/usr/local/
➥ --with-tcl --with-odbc
# make
# make install
Postgresql ist bei den meisten Distributionen fertig
kompiliert vorhanden. Es werden die Packete postgresql, postgresql-lib, postgresql-odbc, postgresql-server,
postgresql-tcl und postgresql-tk benötigt. Bei Suse-Linux
muß man nach der Installation im Yast unter AdministrationKonfigurationsdatei verändern die Variable
START POSTGRES auf yes gesetzt werden. Nach dem
nächsten Systemstart steht das DBMS zur Verfügung und
muß nicht initialisiert werden. Die komplette Dokumentation befindet sich unter /usr/share/doc/packages/postgresql/.
Die Datenbank selber darf nicht unter dem Benutzer
root laufen. Hierfür richtet man einen eigenen Benutzer, z.B. postgresql, ein. Bei einigen Distributio-
Bei allen weiteren Kommandos wird davon ausgegangen,
daß sie vom Nutzer PostgreSQL ausgeführt werden. Das
eigentliche Datenbankprogramm von PostgreSQL heißt
postmaster. Man kann es jetzt starten:
> nohup postmaster -D /usr/local/pgSQL/data
➥ -i 2>&1 /tmp/PostgreSQL.log &
Damit werden die Meldungen der Datenbank in die Datei
/tmp/PostgreSQL.log umgelenkt. Soll die Datenbank beendet werden, muß man nur mit kill den Prozeß beenden2 . In den Quellen befindet sich unter contrib/linux ein Beispielskript, mit dem die Datenbank automatisch mit dem Betriebsystem gestartet und
beendet wird.
Läuft PostgreSQL, sollte man sich erst einmal eine Datenbank zum Testen anlegen. Für den Rest des Textes
wird von einer Datenbank namens spielbank“ ausgegan”
gen. Hierzu dient das Programm createdb
createdb spielbank
Um mit der Datenbank arbeiten zu können, gibt es
für PostgreSQL zwei Programme, das Kommandozeilenprogramm psql und pgaccess, ein GUI Programm
auf Tcl/Tk Basis. Beide können gleichermaßen dazu
benutzt werden, die im Weiteren vorgestellten SQLKommandos auszuprobieren. Beim Aufruf von psql
muß die gewünschte Datenbank mit angegeben werden.
Alle SQL-Statements bei psql müssen mit einem Semikolon beendet werden, zusätzlich bietet das Programm noch
spezielle Kommandos, mit denen zum Beispiel Dateien
eingelesen werden können oder der Aufbau einer Tabelle
angezeigt werden kann. Anstatt die Statements direkt in
psql einzugeben, ist es meistens angenehmer, sie mit einem Editor in eine Datei zu schreiben und diese dann in
psql einzulesen. Dies kann entweder auf der Kommandozeile mit der Option psql -f Dateiname geschehen
oder interaktiv mit \i Dateiname geschehen.3
1 Um die graphische Benutzeroberfläche pgaccess später nutzen zu können, sollte auch Tcl/Tk auf dem System vorhanden sein. Dies ist unter
[3] zu beziehen. Soll PostgreSQL auch von Perl aus benutzt werden, ist bei ./configure auch --perl mit anzugeben.
2 Bei anderen Datenbanken, zum Beispiel Adabas D, muß die Datenbank mit einem speziellen Kommando runtergefahren werden!
3 Die SQL-Statements der Beispiele stehen auf der Homepage des Autors zur Verfügung.
> psql spielbank
Welcome to psql, the PostgreSQL interactive
terminal.
Type:
\copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash
commands
\g or terminate with semicolon to
execute query
\q to quit
spielbank=\q
>
Bei pgaccess kann man sich unter DatabaseOpen mit der Datenbank verbinden, als User
postgresql braucht man nur den Namen der Datenbank
einzugeben. Es bietet eine Reihe von Hilfen bei der
Arbeit mit Datenbanken. So lassen sich oft benutzte
SQL-Statements speichern, einfach neue Tabellen
erstellen usw.
ODBC [6]. Jedes DBMS hat eine eigene Bibliothek, mit
der sich auf die Daten zugreifen läßt. Um eine Anwendnung mit unterschiedlichen DBMS laufen zu lassen, gibt
es ODBC als Zwischenschicht. Es läßt sich mit dem üblichen Vorgehen installieren:4
#
#
#
#
#
#
cd /usr/local
tar -xzf unixODBC-2.0.5.tar.gz
cd unixODBC-2.0.5
./configure --prefix=/usr/local
make
make install
Bevor man eine Datenbank mittels ODBC benutzen
kann, muß erst die Konfigurationsdatei odbc.ini angepaßt
werden. Dies ist in Kapitel 11 beschrieben.
4
Tabellen erzeugen
Das Datenbankdesign, also der Entwurf der Tabellen zur
Datenspeicherung, ist eine anspruchsvolle Aufgabe. Mit
diesem ersten Schritt entscheidet man darüber, wie sinnvoll man mit den Daten umgehen kann. Der saubere Weg
beim Entwurf des Schemas, zum Beispiel mit dem Entity Relationship Modell, wird in diversen Büchern behandelt. Wegen der Kürze der Zeit wird hier mehr ein
handwerklicher“ Ansatz verfolgt. Wichtige Punkte bei
”
der Erstellung des Datenbankschemas sind:
• das Schema muß die zu speichernden Daten mit allen ihren Aspekten abbilden können
• die Integrität des Datenbestandes soll durch das
Schema weitestgehend erzwungen werden
Für PostgreSQL gibt es eine beachtliche Menge an Dokumentation. Diese befindet sich im Unterverzeichnis doc
der Quellen oder kann von [2] unter dem Punkt User’s
”
Lounge“ als HTML geladen werden. Die Beschreibung
der SQL-Kommandos ist in dem User’s Guide enthalten,
die Beschreibung der Tcl-Erweiterung im Programmer’s
Guide.
Ein letzter PostgreSQL spezifischer Tip: Beim Lauf werden Teile der Daten gespeichert, um im Fall eines Absturzes ein konsistentes System zu garantieren. Diese Daten
sollten regelmäßig entfernt werden, bei normalen Betrieb
einmal am Tag. Dies kann mit dem SQL-Kommando vacuum analyze oder mit dem Programm vacuumdb geschehen.
Möchte man die Datenbank in Verbindung mit Staroffice für Serienbriefe verwenden, benötigt man noch unix4 Das
Die Daten werden in Tabellen abgespeichert, wobei jede
Tabelle ein oder mehrere Spalten hat. Jede Spalte wird
durch einen Namen gekennzeichnet und kann Daten eines Datentyps speichern. Folgende Datentypen kann man
bei allen DBMS erwarten:
Name
Beschreibung
boolean
charachter(n)
date
decimal(p,s)
float
smallint
integer
time
varchar(n)
Boolsche Variable
Zeichenkette fester Länge
Datum
Gleitzahlen mit s Nachkommastellen
Gleitkommazahl
Integer [-32768,+32767]
Integer [−232 , 232 − 1]
Zeit
variable Zeichenkette, max n Zeichen
Die meisten DBs haben zusätzliche Typen für spezielle Aufgaben, zum Beispiel IP-Adressen oder Bilder sein.
Konfigurationsprogramm ODBCConfig setzt QT voraus, die gtk+ Alternative gODBCConfig verlangt beim Kompilieren etwas Handarbeit.
Diese Typen können einem viel Arbeit ersparen, allerdings kann man seine Datenstruktur dann nicht einfach
auf eine anderen DB portieren.
Für die Datentypen gibt es auch eine Reihe von Operatoren, die für Vergleiche oder Berechnungen verwendet
werden können. Dies sind zum Beispiel:
Name
Beschreibung
< ,>
<=, >=
<>
NOT, AND, OR
*, +, - ,/
kleiner als, größer als
kleiner gleich, größer gleich
ungleich
logische Operatoren
Zahlenoperationen
Dies ist natürlich nur ein kleiner Ausschnitt. Die meisten Datenbanken bieten viel mehr Operatoren an. Eine ausführliche Übersicht für PostgreSQL findet sich im
User’s Guide“ im Kapitel 5.
”
Zum Anlegen von Tabellen wird das CREATE TABLE
Statement verwendet. Bei ihm werden alle gewünschten
Spalten mit Name und Type aufgezählt.5 6 Mit dem folgenden Statement wird eine einfache Tabelle für die Mitglieder angelegt:
reicht, daß die Spalte mit dem Namen und Vornamen immer einen Eintrag aufweisen muß. Mit CHECK kann eine Bedingung untersucht werden. Geburtsdaten älter als
der 1. Januar 1910 werden hier nicht zugelassen.7 Mit
DEFAULT kann für eine Spalte ein Standardwert vorgegeben werden. Er wird verwendet, wenn kein Eintrag explizit eingegeben wird. Hier wird mit ’today’ automatisch
das aktuelle Datum vergeben.
Generell werden alle Werte, die keine Zahl sind, bei SQL
mit dem einfachen Hochkommata ’ eingefaßt. Dies trifft
nicht nur bei der Definition der Defaultwerte zu, sondern
auch später bei der Eingabe und Abfrage von Daten. Soll
ein Wert ein Hochkomma enthalten, geschieht dies durch
zwei Hochkommata, zum Beispiel
DEFAULT ’eh” es Probleme gibt’
Nachdem die Daten der Mitglieder gespeichert wurden,
sollen als nächstes die Adressen behandelt werden. Der
naheliegendste Gedanke ist natürlich, die Tabelle einfach
um die Spalten für Straße, PLZ und Ort zu erweitern. Allerdings werden bei diesem speziellen Verein bis zu drei
Adressen pro Mitglied verwaltet: eine Postanschrift, eine Firmenanschrift und eine Privatanschrift.8 Die Triviallösung sieht etwa so aus:
Tabelle Mitglieder
CREATE TABLE mitglieder01 (
2
id INTEGER ,
3
name VARCHAR(100) ,
4
vorname VARCHAR(100) ,
5
geburt DATE ,
6
eintritt DATE
7 );
1
Allerdings läßt diese Tabelle noch einige Wünsche offen. Die Mitgliedernummern können mehrfach vergeben
werden, Name und Vorname können leer bleiben, ebenso Geburts- und Eintrittsdatum. Dies soll mit der zweiten
Version behoben werden:
CREATE TABLE mitglieder02 (
id INTEGER PRIMARY KEY,
11
name VARCHAR(100) NOT NULL,
12
vorname VARCHAR(100) NOT NULL,
13
geburt DATE CHECK (geburt > ’1910−01−01’),
14
eintritt DATE DEFAULT ’today’
15 );
9
10
Hier sind neben den Spaltennamen und -typ eine Reihe
weiterer Bedingungen an Spalten gestellt. Mit PRIMARY KEY wird erreicht, daß diese Spalte als Zugriffsschlüssel für die Tabelle angesehen wird. Damit wird
erreicht, daß es keine zwei Tupel (Reihen) mit der selben Mitglieds-Id geben kann. Mit NOT NULL wird er-
Id
Name
Vorname Adresstyp
Strasse
PLZ
1
1
1
Abels
Abels
Abels
Bernd
Bernd
Bernd
Post
Privat
Firma
21073
21073
22304
1476
1476
1476
Yong
Yong
Yong
Yu
Yu
Yu
Post
Privat
Firma
22177
22177
21079
Damit hätte man sich aber ein kapitales Problem eingehandelt. Alle Daten in einer Datenbank sollten redundanzfrei, also nur ein einziges Mal vorliegen. Bei der obigen Tabelle kann ein Mitglied bei gleicher Mitglieds-Id
nicht nur drei verschieden Anschriften, sondern auch drei
verschiedene Namen haben. Dies ist etwas, was durch die
Benutzung von PRIMARY KEY in der ersten Tabelle ja
verhindert werden sollte. Besser ist es dagegen, zusätzlich zur Tabelle mitglieder02 eine weitere Tabelle für die
Adressen zu definieren:
CREATE TABLE adressen01 (
id INTEGER REFERENCES mitglieder02,
19
typ CHAR(6) CHECK (
20
(typ = ’ Post’ ) OR
21
(typ = ’ Firma’) OR
22
(typ = ’ Privat ’ )),
23
strasse1 VARCHAR(100),
17
18
5 Die Sprache SQL kümmert sich wie Fortran nicht um Groß- und Kleinschreibung, wegen der leichteren Unterscheidung wurden hier aber alle
Schlüsselwörter groß geschrieben.
6 Im Programm psql kann man sich mit dem Befehl \d TABELLENNAME die Tabellendefinition anzeigen lassen.
7 Bei der Erzeugung der Tabellen werden Daten im ISO-Format ‘Jahr-Monat-Tag’ angegeben, später kann man das Datumsformat wählen.
8 Das gleiche Problem stellt sich natürlich auch in anderen Bereichen, wo zum Beispiel die Rechnungs- und Lieferanschrift unterschiedlich sein
können.
strasse2 VARCHAR(100),
plz VARCHAR(12),
ort VARCHAR(100),
land CHAR(3)
24
25
26
27
28
die über die Vergleichsoperationen ==,<,> darüber hinaus gehen. Diese sind allerdings nicht immer zwischen
den Datenbanken portabel.
);
Mit der Einschränkung REFERENCES wird dafür gesorgt, daß nur Adressen angelegt werden können, zu denen auch eine Id in der Tabelle Mitglieder02 existiert.
Die Id dient hier als Fremdschlüssel für die Tabelle adressen01.9 Fremdschlüssel sind eine sinnvolle Möglichkeit,
die Konsistenz von Datenbanken über mehrere Tabellen
hinweg zu erzwingen. Es kann nun kein Eintrag mehr aus
der Tabelle mitglieder02 gelöscht werden, ohne daß vorher die dazugehörenden Adressen gelöscht wurden.
Bei dieser Definition bleiben noch ein paar Probleme. Bei
der Postleitzahl ist nur eine Spalte mit Zeichenkette vorgesehen. Dies liegt daran, daß viele Länder (Großbritanien z.B.) eine Kombination von Zahlen und Buchstaben für die Postleitzahl benutzen. Hat man nur Adressen
im Inland, wäre man mit folgender Definition besser bedient:
Und der Euro? Wenn man vor 2002 die Datenbank verwendet, muß man ja mit zwei verschiedenen Währungen
arbeiten. Hierzu kann man alle Geldbeträge gleich in Euro speichern und rechnet sie bei Bedarf in DM um, oder
man speichert die Währung mit. Für letzteres muß aber
die Tabelle rechnungen01 geändert werden. In der Entwurfsphase ist das Löschen und Neuanlegen der Tabelle
am einfachsten. Zum Löschen wird das drop table Statement verwendet:
DROP TABLE mitglieder01;
Die andere Möglichkeit ist, eine Tabelle mit dem ALTER
TABLE Statement zu ändern. Allerdings ist das Statement sehr beschränkt in seinen Fähigkeiten. Zum hinzufügen einer weitern Spalte reicht es aber:
ALTER TABLE rechnungen01
ADD COLUMN waehrung CHAR(3);
45 ALTER TABLE rechnungen01
46
ALTER COLUMN waehrung SET DEFAULT ’EUR’;
43
44
plz INTEGER CHECK (plz > 1000 AND plz < 100000)
Allerding müßte vor dem Ausdrucken dann die vierstelligen Postleitzahlen von Dresden und Umgebung mit einer führenden Null versehen. Noch besser ist natürlich eine getrennte Speicherung von Straße, Hausnummer und
Ort, damit man anhand einer PLZ-Datenbank automatisch die Gültigkeit der Adresse überprüfen kann. Beim
Land bietet es sich an, eine Tabellen mit Länderkürzeln
entsprechend ISO 3166 [10] anzulegen und diese dann
als Fremdschlüssel zu verwenden.
Als letztes müssen noch die Rechnungen der Mitglieder gespeichert werden. Die Definition der Tabelle bietet
nichts wesentlich neues:
CREATE TABLE rechnungen01 (
id INTEGER REFERENCES mitglieder02,
32
jahr INTEGER CHECK ((jahr > 1995) AND
33
( jahr < ( DATE PART(’year’, TIMESTAMP ’now’) +5))
34
),
35
rechnungsbetrag DECIMAL(9,2),
36
datum DATE DEFAULT ’today’,
37
eingangsbetrag DECIMAL(9,2),
38
spesen DECIMAL(9,2),
39
eingangsdatum DATE,
40
mahnungsdatum DATE
41 );
30
31
Bei dem Rechnungsjahr wird untersucht, ob es nach 1995
aber innerhalb der nächsten zwei Jahre liegt. Dies ist ein
kleines Beispiel, was mit den eingebauten Funktionen
für die Zeitberechnung angefangen werden kann. Für die
meisten Datentypen gibt es eine Reihe von Funktionen,
9 Das
DBMS MySQL unterstützt keine Fremdschlüssel.
5
Und hinein !
Nachdem die Tabellen definiert sind, müssen natürlich
Daten in die Datenbank gefüllt werden. Hierzu ist das
Statement INSERT INTO vorgesehen.
INSERT INTO mitglieder02 VALUES
(1, ’ Mustermann’,’Hans’,’1970−01−01’,’2001−03−13’);
3 INSERT INTO mitglieder02 (id,name,vorname) VALUES
4
(2, ’ Musterfrau’, ’ Hanna’);
1
2
In der einfache Form werden Werte für alle Spalten angegeben. Diese müßen in der Reihenfolge der Tabellenspalten angegeben werden. Alternativ kann man die Spalten angeben, die man füllen möchte. Spalten, die keinen
Eintrag bekommen, bleiben leer oder werden mit dem
Defaultwert gefüllt. Es müssen aber mindestens die Spalten gefüllt werden, die als Primär- oder Fremdschlüssel
definiert wurden oder die NOT NULL Einschränkung
haben. Verstößt man gegen die Tabellenstruktur bei der
Eingabe, sei es durch einen falschen Typ oder einen
doppelt vergebenen Primärschlüssel, bekommt man eine Fehlermeldung und das ganze Statement wird nicht
durchgeführt.
6
Wo bist Du ?
Nachdem die Datenbank nun gefüllt ist, geht es an
den wichtigsten Punk, das Abfragen. Die mächtigen
Möglichkeiten der Abfrage machen aus den relationalen
Datenbanken das Werkzeug, welches bei vielen Aufgaben unverzichtbar ist. Aus Platzgründen wird bei den folgenden Beispielen auf die Abbildung der Ergebnisse verzichtet, am besten vollzieht man die Beispiele selber am
Rechner nach.
Zur Abfrage wird das SELECT FROM Statement verwendet. Seine einfachste Form in Zeile 1 gibt alle Einträge der Tabelle aus. Möchte man nur einige Spalten im
Ergebniss haben, kann dies wie in Zeile 2 eingeschränkt
werden.
SELECT * FROM mitglieder02;
SELECT name FROM mitglieder02;
3 SELECT COUNT(id) FROM mitglieder02;
4 SELECT SUM(rechnungsbetrag) FROM rechnungen01;
5 SELECT SUM(rechnungsbetrag) / COUNT(rechnungsbetrag)
6
FROM rechnungen01;
7 SELECT DISTINCT(ort) from adressen01;
1
2
Statt der eigentlichen Inhalte lassen sich auch Berechnungen auf dem Ausgang ausführen. Es sind alle Möglichkeiten zugelassen, die die Datenbank an Berechnungen bietet. Hier bekommt man als Ausgabe die
Anzahl der Mitglieder (Z. 3), die Summe der Rechnungsbeträge aller Rechnungen (Z. 4) oder den mittleren Rechnungsbetrag aller Rechnungen (Z. 5–6). Datebankfunktionen stehen nicht nur für numerische Typen
zur Verfügung, mit dem DISTINCT Schlüsselwort läßt
sich die Ausgabe von Doubletten verhindern (Z. 7).
Alle bisherigen Abfragen dient immer eine ganze Tabelle als Grundlage, hier kann man die Abfrage weiter
einschränken. Man kann dabei vorgeben, daß ein oder
mehrere bestimmte Werte in einer Zeile enthalten sein
müssen (Z. 10, 11), oder auch einen Wertebereich einschränken (Z. 12). Mit dem Schlüsselwort ISNULL lassen sich Einträge selektieren, die noch nicht belegt sind,
dies sind hier alle unbezahlten Rechnungen.
SELECT * FROM adressen01 WHERE id=1;
SELECT * FROM adressen01 WHERE id=1 AND typ=’Post’;
12 SELECT
* FROM rechnungen01
13
WHERE rechnungsbetrag < 20;
14 SELECT
* FROM rechnungen01
15
WHERE eingangsbetrag ISNULL;
10
11
Ist man von Sprachen wie Tcl, Perl oder Python die ganze Macht regulärer Ausdrücke gewöhnt, wird man von
SQLs Fähigkeiten enttäuscht sein. Es gibt nur zwei Wildcard: % für ein oder mehrere Zeichen und für genau ein
Zeichen und keine vollwertigen regulären Ausdrücke. So
bekommt man aus Zeile 17 Mustermann und Musterfrau,
aus Zeile 18 hingegen nur Mustermann da Hanna zuviele Buchstaben hat.10 Einen Ausweg bietet der Operator
10 PostgreSQL
IN an, er vergleicht die Einträge mit einer Liste gültiger
Werte (Z. 19–20). Dies funktioniert mit allen Datentypen.
SELECT * FROM mitglieder02 WHERE name like ’Muster%’;
SELECT * FROM mitglieder02 WHERE vorname like ’Ha ’;
19 SELECT
* FROM mitglieder02
20
WHERE vorname IN (’Hans’,’Hanna’);
17
18
Alle Operationen fanden bisher auf einer Tabelle statt.
Nun sollen auch die Daten von mehreren Tabellen verknüpft werden. Das Statement in Zeile 22 gibt jedoch
bestimmt nicht das gewünschte Ergebniss, hier werden
alle Kombinationsmöglichkeiten aus den beiden Tabellen zurückgegeben. Statt der erwarteten 6 Ergebnisse
erhält man deren 12. Um die Mitglieder mit den zu ihnen
gehörenden Adressen zu erhalten, muß man ein Statement wie in Zeile 23 – 25 verwenden. Da die Spalte id
in beiden Tabellen vorhanden ist, muß mit dem vorangestellten Tabellennamen gekennzeichnet werden, aus welcher Tabelle der Wert gewünscht ist.
SELECT * FROM mitglieder02, adressen01;
SELECT mitglieder02.id, name, vorname, strasse2, ort
24
FROM mitglieder02, adressen01
25
WHERE mitglieder02.id = adressen01.id;
26 SELECT id, name, vorname
27
FROM mitglieder02
28
WHERE mitglieder02.id IN (
29
SELECT id FROM rechnungen01
30
WHERE eingangsbetrag ISNULL
31
);
22
23
Eine andere Art, mehrere Tabellen miteinander zu verknüpfen, sind sogenannte Subselects.11 Hier wird das Ergebniss einer Abfrage als Eingang für eine weitere Abfrage verwendet. Das Statement in Zeile 26 – 31 ist ein Beispiel hierfür, es gibt die Mitglieds-Id, Namen und Vorname derjenigen Mitglieder aus, die noch nicht bezahlt
haben.
Wenn man endlich Ergebnisse abgefragt hat, an denen
man interessiert ist, kann man mit ORDER BY noch die
Reihenfolge der Anzeige beeinflussen. Die Spalte, nach
der sortiert werden soll muß dabei in der Ausgabe enthalten sein. Geordnet wird nach der normalem Reihenfolge
des jeweiligen Datentyps. Die kann die Größe oder die
alphabetische Reihenfolge sein.12 Im Normalfall werden
die Ergebnisse in aufsteigender Reihenfolge ausgegeben,
mit DESC läßt sich die Reihenfolge auch umkehren.
33
34
SELECT * FROM mitglieder02 ORDER BY geburt;
SELECT * FROM mitglieder02 ORDER BY name desc;
In den Beispieldateien sind 30 Beispielmitglieder enthalten, an denen man verschiedene Statements ausprobieren
kann.
bietet noch mehr Operatoren für reguläre Ausdrücke an, diese gehören aber zu keinem SQL-Standard.
werden nicht von MySQL unterstützt.
12 Wenn da nicht die Umlaute wären. PostgreSQL kennt leider nicht die im Deutschen übliche Einordnung der Umlaute (Ac,Ae,Ä,Af). Dies muß
man in einem externen Programm realisieren oder auf ADABAS D zurückgreifen. Dort lassen sich beliebige Sortierreihenfolgen erreichen.
11 Subselects
7
Oder so ?
Endlich hat ein Mitglied seine Beitrag bezahlt, nun soll
das auch in der Datenbank geändert werden. Zum Ändern
der Daten dient das UPDATE Statement.
UPDATE mitglieder SET eingangsbetrag=23.20
WHERE jahr=2001 AND
3
id = ( SELECT id FROM mitglieder02
4
WHERE name=’Mustermann’);
5 UPDATE rechnungen01 SET
6
spesen=spesen+10 WHERE spesen=0;
1
2
Bei dem UPDATE Statement sind die gleichen Einschränkungen wie bei SELECT möglich, aber auch einfache Berechnungen wie in Zeile 5.
Ein letzter Punkt zu Datenbearbeitung ist das Löschen.
Hierfür gibt es das DELETE Statement. Mit dem Statement wird immer eine ganze Zeile gelöscht, das Löschen
einzelner Spalten ist nicht möglich. Vorsicht mit dem folgenden Statement, damit werden alle Daten einer Tabelle
gelöscht!
DELETE FROM mitglieder01;
8
Ferner liefen . . .
Alle Eingaben und Abfragen wurden bisher als
Datenbank-Superuser durchgeführt. Das ist allerdings
genauso sinnvoll, wie immer als root unter Unix zu arbeiten. Bei Datenbanken lassen sich ebenso wie unter
Unix Benutzer einrichten und Zugriffsrechte zuordnen.
Es besteht keine automatische Kopplung zwischen einem
Datenbanknutzer und einem Systemnutzer. Meldet man
sich mit psql bei der Datenbank an, wird allerdings bequemerweise davon ausgegangen, daß die beiden Namen
identisch sind. Zum Einrichten eines Nutzers dient das
CREATE USER Statement:
CREATE USER abfrage WITH password ’fragen’;
CREATE USER aenderung WITH password ’aendern’
3
VALID UNTIL ’2001−12−31’;
4 CREATE USER spielen WITH password ’testen’
5
CREATEDB CREATEUSER;
1
2
6
GRANT select ON mitglieder02, adressen01,
8
rechnungen01 TO public;
9 GRANT insert,update ON mitglieder02, adressen01,
10
rechnungen01 TO aenderung;
11 GRANT all ON mitglieder02, adressen01, rechnungen01
12
TO spielen;
7
13
Es werden zuerst zwei Nutzer eingerichtet und ihnen ein
Passwort zugeteilt. Bei dem Nutzer aenderung wird außerdem seine Gültigkeit zeitlich eingeschränkt. Der dritte
Nutzer bekommt zusätzlich noch die Fähigkeit, neue Datenbanken und Nutzer anzulegen. Nachdem die Nutzer
angelegt wurden, müssen ihnen noch Rechte zugewiesen
werden. Hierfür dient das GRANT Statement. Bei den
Rechten wird zwischen SELECT, INSERT, UPDATE
und DELETE unterschieden, mit ALL sind alle Zugriffe
gemeint. Hiermit können zum Beispiel Datenbankbenutzer angelegt werden, die nur Abfragen können, solche,
die nur Änderungen vornehmen können, und solche, die
neue Mitglieder anlegen oder alte löschen können. Dies
kann entweder für jeden Nutzer explizit angegeben werden oder mit PUBLIC für alle Nutzer.
9
Für Fortgeschrittene
Alle Datumsangaben sind bisher im ISO-8601 Format
Jahr-Monat-Tag eingegeben worden, was in Deutschland
eher ungewöhnlich ist. Die meisten Datenbanken bieten
an, das Format der Datumsangabe ändern zu können, bei
PostgreSQL geschieht dies folgendermaßen:
SET datestyle TO ’European’;
Bei den Anforderungen an ein DBMS war gefordert, daß
eine Reihe von Eingaben zu einer Einheit (Transaktion)
zusammengefaßt werden können. Im Normalfall wird jedes SQL-Statement als Einheit angesehen, dies wird als
AUTOCOMMIT-Modus bezeichnet. Sollen mehrere Befehle zu einer Transaktion zusammengefaßt werden, geschieht dies folgendermaßen:
BEGIN work;
INSERT INTO mitglieder02 (id,name,vorname) VALUES
5
(3, ’ Musterstudent’,’Hanno’);
6 INSERT INTO adressen01 VALUES
7
(3, ’ Post’ , ’ ’ , ’ä Lmmersieth 90’,’22305’,’Hamburg’,’DE’);
8 COMMIT work;
3
4
Tritt ein Fehler während der Transaktion auf, wird der
Datenbestand komplett auf den alten Stand gebracht,
was als Rollback bezeichnet wird. Dies kann alternativ
während einer Transaktion auch mit dem ROLLBACK
Statement ausgelöst werden. Durch den Transaktionsmechanismus wird Integrität von zusammengehörenden Daten sichergestellt.
Manchmal kommt es vor, daß die Daten zwar in einem
sauberen Schema vorliegen, man aber gerne eine andere
Anordnung hätte. Statt der sauberen Aufteilung bräuchte
man eventuell eine große Tabelle, oder man möchte einen
Nutzer nur auf Teile einer Tabelle zugreifen lassen. Dies
kann mit Nutzersichten erfolgen. Diese sind für den Benutzer wie normale Tabellen zu benutzen, sind aber nur
eine virtuelle Abbildung von Daten aus real existierenden Tabellen. Sie entsprechen in etwa einem logischen
Link im Dateisystem, die Daten sind nur einmal vorhandend, können aber mit verschiedenen Namen abgefragt
werden. Nutzersichten werden mit dem CREATE VIEW
Statement angelegt.
CREATE VIEW mgaddr AS SELECT
mitglieder02. id , name, vorname, eintritt , geburt,
12
strasse1, strasse2, plz , ort , land
13
FROM mitglieder02, adressen01
14
WHERE adressen01.id = mitglieder02.id
15
AND typ = ’Post’;
vor. Der Generator zur Erstellung von einfachen Oberflächen (Forms) unter pgaccess ist so zur Zeit aufwendig
zu bedienen, daß man mit der kompletten Eigenentwicklung schneller ist (siehe Kapitel 12).
10
11
Hiermit wird eine Nutzersicht angelegt, die alle Daten
eines Mitglieds in Kombination mit seiner Postanschrift
enthält. Mit dieser Nutzersicht läßt sich wie mit einer normalen Tabelle arbeiten, nur daß man hier alles zusammen
hat, was man für Anschreiben et cetera benötigt. Was
in die Nutzersicht einfließen soll, wird mit der gleichen
Syntax wie bei dem SELECT Statement angegeben. Anstatt ein häufig benötigtes Statement immer wieder auszuführen, bietet sich dann das Anlegen einer Benutzersicht an.13
10
Eine der häufigsten Anwendungen für Datenbanken ist
als Datenquelle für Serienbriefe, Rechnungen und dergleichen. Als Textverarbeitung unter Linux bietet sich
Staroffice an. Dieses Programm kann aber nicht direkt mit einer Datenbank kommunizieren, es benötigt
als Zwischenschicht ODBC. Dies ist ein Interface, welches Anwendungsprogrammen einen einheitlichen Zugriff ermöglicht, mehr oder weniger unabhängig von dem
zu Grunde liegenden DBMS.
Zur Sicherheit
PostgreSQL ist ziemlich robust was Störungen von Außen betrifft. Es muß nicht extra runtergefahren werden,
und mangelnde Pflege (VACUUM !) wird auch nur mit
sinkender Leistung bezahlt. Dennoch sollte man auch
über ein Backup nachdenken. Es gibt zwei mögliche Formen des Backups. Entweder man sichert die Dateien, in
denen PostgreSQL seine Daten speichert. In diesem Beispiel wären es alle Dateien unter /usr/local/pgSQL/data.
Alternativ kann man den Inhalt und das Datenbankschema in einfache ASCII-Dateien mit den SQL-Statements
schreiben. Aus diesen Dateien läßt sich dann jederzeit
wieder eine neue Datenbank aufsetzen.14 . Zu diesem
Zweck gibt es das pg dump Programm, mit ihm lassen
sich solche Sicherungen anfertigen:15
> pg_dump -s spielbank > schema.SQL
> pg_dump -a -d spielbank > daten.SQL
11 Zugreifen !
Nachdem man sich mit den SQL-Statements vertraut gemacht hat, sollen die Daten in irgendeiner Form verwendet werden. Mit pgSQL lassen sich Daten in ASCII oder
HTML-Tabellen ausgeben, pgaccess bietet auch den Imbzw. Export von Dateien im CSV-Format an. Außerdem
lassen sich pgaccess unter dem Punkt Reports Ausdrucke
aus der Datenbank erstellen, diese liegen in Postscript
13 Eine andere Möglichkeit sind Funktionen. Diese werden einmal definiert und können dann durch das DBMS ausgeführt werden. Siehe in [5]
unter CREATE FUNCTION.
14 Dieser Weg bietet sich auch an, wenn man auf einen neuen Rechner oder zu einem neuen DBMS wechselt.
15 Die Benutzer lassen sich so nicht sichern, hier sollte man am einfachsten die Datei mit den SQL-Statements aufheben.
Unter Linux dient unixODBC [6] als ODBC-Schicht. Bevor man auf eine Datenbank zugreifen kann, muß diese in der Konfigurationsdatei odbc.ini beschrieben werden. Am einfachsten ruft man (als root) das Konfigurationsprogramm (g)ODBCConfig auf. In diesem Programm
muß zuerst ein Treiber für PostgreSQL eingerichtet werden. Dies geschieht unter dem Punkt DriversAdd .
Hier muß man die Namen von zwei Bibliotheken eintragen. Die eine wird als Driver bezeichnet, die andere als
Setup. Für PostgreSQL sind dies die Bibliotheken libodbcpSQL.so und libodbcpSQLS.so, beide liegen unter /usr/local/lib.
Nachdem mit dem Treiber die Verbindung mit einem
DBMS definiert wurde, kommt die Verbindung zu einem DBS. Hier gibt es die Möglichkeit, unter System
DNS eine Konfiguration für alle Benutzer einzurichten
oder unter User DNS für einen Nutzer. Um einen systemweiten Zugriff einzurichten kommt man mit System DNSAdd zu einem Dialog, wo man den bereits
eingerichteten Treiber selektiert und dann Ok drückt.
In diesem Dialog kann man dann einstellen, welche Datenbank man abfragen möchte.
Als nächstes kann man dann in Staroffice die Datenbank als Quelle einrichten. Unter DateiNeuDatenbank läßt sich ein Dialog zum Einrichten einer Datenbank öffnen.
Um die Datenbank mit einem Textdokument nutzen zu
können, wählt man unter BearbeitenDatenbank austauschen die gewünschte Datenbank aus. Danach kann
man in das Dokument Verweise auf einzelne Spalten
einfügen. Dies geht entweder mit EinfügenFeldbe-
fehle. Oder man läßt sich mit Ansicht Aktuelle
Datebank die Datenbank einblenden. Mit Drag’n Drop
lassen sich dann die einzelnen Felder aus den Tabellenköpfen in das Dokument ziehen. Jetzt sollte auch klar
sein, wofür die Nutzersicht mgaddr erzeugt wurde. Damit kann man bequem alle notwendigen Felder für Briefe handhaben, ohne über mehrere Tabellen arbeiten zu
müssen.
Ist man mit der Erstellung des Textes fertig, ruft man
die Serienbrieffunktion erneut auf. Dort kann angegeben
werden, ob die komplette Tabelle, oder bestimmte Zeilen
benutzt werden sollen. Diese müssen vorher in der Datenbankansicht selektiert werden. Staroffice füllt dann die
Daten aus der Datenbank in das Dokument ein und man
kann recht bequem allen Mitgliedern eine neue Rechnung zukommen lassen.
Der Funktionsumfang von Staroffice geht weit über das
Beschriebene hinaus, neben einfachem Drucken lassen
sich auch Dokumente abhängig von Datenbankeinträgen
formatieren oder Serien-Emails erzeugen. Hier sei auf
die Seite von Werner Roth verwiesen http://www.
wernerroth.de/staroffice.
12 Selbst gemacht
Ist Staroffice auch recht flexibel, was das Ausdrucken angeht, bleiben doch manchmal Wünsche offen oder man
möchte die Datenbank in Verbindung mit dem Internet
verwenden. Hierfür muß aus selbstgeschriebenen Programmen auf die Datenbank zugegriffen werden. Am
einfachsten geht dies mit Skriptsprachen wie Tcl oder
Perl.
Es gibt wohl kaum ein DBMS ohne Tcl-Erweiterung,
bei Adabas D wird diese flexible Skriptsprache sogar
für die Systemwerkzeuge eingesetzt. Im Zusammenhang
mit PostgreSQL kann man die Tcl-Erweiterung pgtcl verwenden. Diese befindet sich nach der Installation in dem
Verzeichnis /usr/local/lib. Man kann sie entweder in tcl
durch direktes Laden verwenden
load /usr/local/lib/libpgtcl.so
oder man legt (als Root) eine neue pkgIndex.tcl Datei
dort an.
/root# cd /usr/local/lib
Directory: /usr/local/lib
local/lib# tclsh
% pkg_mkIndex . "*.so"
% package require Pgtcl
1.3
Zuerst muß eine Verbindung mit einer Datenbank hergestellt werden, diese wird auch als Datenbankhandle
bezeichnet. Dazu dient das Kommando pg_connect,
dem eine Zeichenkette mit dem notwendigen Angaben
übergeben wird.
Das Datenbankhandle wird dann bei Abfragen benutzt,
um das gewünschte DBS zu kennzeichnen. Damit lassen
sich auch mehrere Verbindungen zu verschiedenen DBS
in einem Skript verwenden. Die Abfrage benutzt normale SQL-Statements. Sie werden mit dem Kommando
pg_exec an die Datenbank geschickt. Als Antwort bekommt man nicht das Ergebnis der Anfrage zurück, sondern ein Resulthandle, auch als Cursor bezeichnet. Mit
diesem Cursor lassen sich dann die Ergebnisse der Abfrage, aber auch Informationen wie Fehlermeldungen oder
Anzahl der Resultate abfragen. Hierzu dient das Kommando pg_result. Der Sinn dieses zweistufigen Verfahrens ist es, daß man so über mehrere 1000 Ergebnisse
von mehreren Abfragen arbeiten kann. Würde man alle
Ergebnisse direkt aus der Datenbank erhalten, könnte es
für kleinere Systeme wegen der schieren Datenmenge zu
Schwierigkeiten führen. Benötigt man die Ergebnisse einer Abfrage nicht mehr, sollte man den Cursor wieder
Löschen. Das Kommando pg_result bietet verschiedene Möglichkeiten, die Ergbenisse oder Informationen
über sie abzufragen, in dem folgenden Beispiel sind nur
die wichtigsten vorgestellt. Die komplette Dokumentation über Pgtcl findet sich im Programmer’s Guide“.
”
% package require Pgtcl
1.3
% set handle [pg_connect -conninfo
➥ "dbname=spielbank user=spielen
➥ password=testen"]
pgsql4
% set cursor [pg_exec $handle
➥ "select name,vorname,id
➥ from mitglieder02"]
pgsql4.1
% pg_result $cursor -status
PGRES_TUPLES_OK
% pg_result $cursor -numTuples
2
% pg_result $cursor -assign array1
array1
% parray array1
array1(0,id) = 1
array1(0,name) = Mustermann
array1(0,vorname) = Hans
array1(1,id) = 2
array1(1,name) = Musterfrau
array1(1,vorname) = Hanna
% pg_result $cursor -assignbyidx array2
array2
% parray array2
array2(Musterfrau,id) = 2
array2(Musterfrau,vorname) = Hanna
array2(Mustermann,id) = 1
array2(Mustermann,vorname) = Hans
% set num [pg_result $cursor -numTuples ]
2
% for {set i 0} {$i < $num} {incr i} {
puts [pg_result $cursor -getTuple $i]
}
Mustermann Hans 1
Musterfrau Hanna 2
% pg_result $cursor -clear ;# Cursor ölschen
% pg_disconnect $handle ;# Verbinung beenden
Alternativ gibt es mit pg_select ein Kommando, mit
dem man gleich über die erhaltenen Ergebnisse kursiert.
% pg_select $handle
➥ "select name,vorname from mitglieder02" result
➥ { parray result
puts "--Tupel--" }
result(.command) = update
result(.headers) = name vorname
result(.numcols) = 2
result(.tupno) = 0
result(name) = Mustermann
result(vorname) = Hans
--Tupel-result(.command) = update
result(.headers) = name vorname
result(.numcols) = 2
result(.tupno) = 1
result(name) = Musterfrau
result(vorname) = Hanna
--Tupel--
Da SQL-Statements einfache Zeichenketten sind, lassen
sie sich mit den Möglichkeiten von Tcl einfach erzeugen. Mit Vorsicht sollte man dabei mit Benutzereingaben umgehen. Eine falsch formatierte Datumsangabe bei
der Abfrage oder Eingabe wird von dem DBMS mit
einer Fehlermeldung bedacht. Diese kann man entweder an den Benutzer weiterreichen, damit er die Eingaben ändern kann. Noch besser ist es, dafür zu sorgen,
daß die Eingaben nur in einem gültign Format vorliegen können. Unter Tk gibt es die Möglichkeit, Benutzereingaben in Entry-Widgets gleich bei der Eingabe zu
überprüfen. Diese sind in der Dokumentation des Entrywidgets bei den Punkten -validate und -validatecommand
erklärt. Einfacher machen es einem natürlich Widgets,
deren Ausgabe man selber bestimmen kann wie bei den
checkbuttons, dem tk optionMenu, der spinbox (Tk 8.4)
oder der ComboBox (aus den BWidgets). Hier braucht
keine Überprüfung mehr stattzufinden.
Bücher und Verweise
[1] A NDREAS H EUER , G UNTER S AAKE, Datenbanken: Konzepte
und Sprachen, MITP-Verlag, Bonn, 2000
[2] Homepage
von
PostgreSQL.org
PostgreSQL:
http://www.de.
[3] Homepage von Tcl und Tk sind bei Sourceforge http://tcl.
sourceforge.org
[4] Homepage von pgaccess: http://flex.ro/pgaccess/
[5] PostgreSQL User’s Guide, zu beziehen von [2]
[6] Homepage von unixODBC: http://wwww.unixODBC.org
[7] Homepage von tclodbc:
projects/tclodbc/
http://sourceforge.net/
[8] Homepage von MySQL: http://www.mySQL.com
Mit Hilfe von Tk lassen sich dann benutzerfreundliche
Oberflächen für die Datenbank erstellen, die ganz an das
Zielpublikum angepaßt werden können. Die Abbildung
unten zeigt das Programm STGmitglieder. Es ist eine
graphische Benutzeroberfläche für die Mitgliederverwaltung. Mit ihr lassen sich bequem die Daten einzelner Nutzer anlegen und ändern, einzelne Mitglieder suchen et cetera.
[9] Tim Perdue: MySQL and PostgreSQL Compared, http://
www.phpbuilder.com/columns/tim20000705.php3
[10] Zwei- und dreibuchstabige Länderkennzeichnung, ftp://ftp.
ripe.net/iso3166-countrycodes
Über den Autor:
Carsten Zerbst ist wissenschaftlicher Mitarbeiter an der Technischen
Universtät Hamburg-Harburg. Arbeitsgebiet bis Ende des Jahres ist die
Dienstintegration von Schiffen mit Hilfe von CORBA, danach sucht
er neue Aufgaben. Die Skripte für diesen Vortrag sind unter http:
//www.tu-harburg.de/˜skfcz/LT2001 zu bekommen.
Herunterladen