Datenbanken-Praktikum SS2012

Bewertungen

Hr. Krechel kündigt für Blatt 11 an: Das letzte Blatt das am Dienstag ausgegeben wird korrigiere ich als kleine Entschädigung für die späte Versorgung mit den nötigen Informationen alleine.

Ich melde die Punktzahlen am MO 16.7. an Hr. Krechel. Bitte Einsprüche bis dahin!

Jetzt neu (10.7.) Es gibt jetzt die vollständige Bewertung von Blatt 10 eingetragen. Bitte rechnet wie üblich nochmal nach, und prüft auch, ob ihr denkt dass euch weitere Bonuspunkte zustehen ;-). Die Korrekturvorgaben findet ihr unten im Abschnitt "Blatt 10"

Jetzt neu (25.6:) Bewertung von Blatt 7 ist jetzt da. Bitte rechnet meine Punktzahlen nochmal nach! Die Korrekturvorgaben findet ihr unten im Abschnitt "Blatt 7". Wie ihr dort erkennen könnt, gibt es bis zu 7 Bonuspunkte für Sonderfeatures. Da ich die Bonus-Sachen nicht mehr im Kopf habe und nicht alle eure Abgaben nochmal durchklicken will: prüft nach, ob ihr zusätzliche Entitäten erfunden hattet, und meldet euch bei mir ;-). Ich habe allerdings versucht, eher weniger abzuziehen, um das aktuelle Chaos ein wenig auszugleichen.

Update 20.6.:
In den Bewertungen von Blatt 7: habe ich teilweise Kritikpunkte der Form "Keine Beschreibung der Umformungen abgegeben (Normalisierungen, Tabellen für Relationen)." eingetragen. Zumindest den Teil "Tabellen für Relationen" hatte ich aber nicht in der Liste "abzugebende Dinge" weiter unten stehen. Deshalb gibt es dafür keine Punktabzüge. Nur Normalisierungen hätten beschrieben werden sollen, aber falls das fehlt werde ich nicht allzuviel abziehen.

Danke für eure Evaluation: SS12-Datenbanken_P-FG.pdf

Blatt 11

Korrektur erfolgt, wie oben angekündigt, durch Hr. Krechel. Also unbedingt über ReadMi abgeben, nicht per Mail an mich.

Falls eine Fragestunde nötig ist, meldet euch per Mail bei mir zwecks Koordinierung eines Termins. Ansonsten könnt ihr mir Fragen per Mail schicken.

Ein paar Hinweise:

Blatt 9

Da wir die letzten drei Statements des Blattes nicht besprochen hatten, hier die Krechelsche Musterlösung:

Wer sitzt im Zimmer mit der größten Zimmernummer?

SELECT D.name FROM dozent D WHERE D.zimmernummer = (SELECT
max(D.zimmernummer) FROM dozent D);
Was sind die Vornamen von Dozenten, die Veranstaltungen halten, die sich in der Veranstaltungsnummer nur um 1 voneinander unterscheiden?
SELECT DISTINCT D.vorname FROM dozent D, veranstaltung V
WHERE V.dozent=D.kuerzel AND
V.nummer=ANY(SELECT VV.nummer+1 FROM veranstaltung VV
WHERE VV.dozent=D.kuerzel);
Wie viele Dozenten halten Veranstaltungen, deren Nummer kleiner ist als der Mittelwert der Nummern aller Veranstaltungen?
SELECT count(DISTINCT dozent) FROM veranstaltung V
WHERE V.nummer < (SELECT avg(nummer) FROM veranstaltung);

Blatt 10Blatt 10

Hr. Krechels Korrekturvorgaben als Leitfaden: KorrekturvorgabenBlatt10.pdf
Abweichung zu Read.mi: Blatt 10 kann bis Dienstag 26.6. 23:59 per Mail bei mir abgegeben werden.
Im folgenden ein paar Beispiele für Funktionen. Hoffentlich helfen sie weiter.

Beispiel 1

In diesem Beispiel gibt es:
Tabellen erzeugen
create table Kunde
(
  Name varchar(100) not null,
  Geburtsdatum date,
  constraint Kunde_PK primary key (Name)
);


create table Wohnort
(
  ID serial not null,
  Postleitzahl char(5) not null,
  Ort varchar(100) not null,
  Strasse varchar(100) not null,
  Hausnummer varchar(5) not null,
  constraint Wohnort_PK primary key (id)
);
create unique index Wohnort_IX on Wohnort (Postleitzahl, Ort, Strasse, Hausnummer);


create table KundeWohnort
(
  Kundenname varchar(100) not null,
  WohnortID int not null,
  constraint KundeWohnort_PK primary key (Kundenname),
  constraint KundeWohnort_FK1 foreign key (Kundenname) references Kunde(Name) on delete cascade,
  constraint KundeWohnort_FK2 foreign key (WohnortID) references Wohnort(ID) on delete cascade
);
Besonderheit hierbei: für Primary und Foreign Key habe ich Namen angegeben. Das hat den Vorteil, dass man die Schlüssel danach explizit löschen kann. Das geht z.B. so:

alter table KundeWohnort drop constraint KundeWohnort_FK2;

Funktion für Erzeugen von Kunde und Wohnort
Diese Funktion legt einen Kunden an. Beim Wohnort wird geprüft, ob es ihn schon gibt. Wenn nicht wird er angelegt. Anschließend werden Kunde und Wohnort verbunden.

CREATE or replace FUNCTION KundeErzeugen(varchar, date, char, varchar, varchar, varchar)
RETURNS void
AS'
DECLARE
PName ALIAS FOR $1;
PGeburtsdatum ALIAS for $2;
PPostleitzahl ALIAS for $3;
POrt ALIAS for $4;
PStrasse ALIAS for $5;
PHausnummer ALIAS for $6;
zeile Wohnort%ROWTYPE;
BEGIN

SELECT * INTO zeile FROM Wohnort where Postleitzahl = PPostleitzahl and Ort = POrt and Strasse = PStrasse and Hausnummer = PHausnummer;
IF NOT FOUND THEN
  insert into Wohnort (Postleitzahl, Ort, Strasse, Hausnummer) values (PPostleitzahl, POrt, PStrasse, PHausnummer);
END IF;

--Kunde erzeugen:
insert into Kunde (Name, Geburtsdatum) values (PName, PGeburtsdatum);

--ID des Wohnorts holen. Der ist entweder vorhanden oder neu.
SELECT * INTO zeile FROM Wohnort where Postleitzahl = PPostleitzahl and Ort = POrt and Strasse = PStrasse and Hausnummer = PHausnummer;

insert into KundeWohnort (Kundenname, WohnortID) values (PName, zeile.ID);

END;
' LANGUAGE 'plpgsql';

Daten anlegen

select KundeErzeugen('Hans Mustermann', to_date('15.06.1960', 'DD.MM.YYYY'), '65321', 'Wiesbaden', 'Biebricher Allee', '12');
select KundeErzeugen('Gaby Mustermann', to_date('29.02.1990', 'DD.MM.YYYY'), '65321', 'Wiesbaden', 'Biebricher Allee', '12');

select * from wohnort;
select * from kunde;
select * from kundeWohnort;
Besonderheit beim Aufruf der Funktion: man beachte die Konvertierung des Datumsparameters: wann immer man in einem SQL-Statement ein Datum als String angibt, sollte man dieses über die Funktion "to_date" eingeben, denn hier kann man das Format des Datums deklarieren. Ansonsten bekommt man Probleme, wenn der Server englisches Datumsformat verwendet, im SQL-String aber ein deutsches Datum steht. Im günstigsten Fall gibt das eine Fehlermeldung ;-).
Dicke Besonderheit: ich habe im zweiten Fall den 29.2. angegeben, den es 1990 wohl nicht gab. PostgreSQL konvertiert das automatisch in den 1.3.1990. Dafür ein großes "Pfui!" von mir!

Danach aufräumen:
Beim "drop" müssen die Parametertypen angegeben werden!

drop FUNCTION kundeerzeugen(varchar, date, char, varchar, varchar, varchar);
drop table KundeWohnort;
drop table Kunde;
drop table Wohnort;

Beispiel 2: Funktion mit Fehlermeldung

Im folgenden wird die Funktion "KundeLoeschen" angelegt, die prüft, ob der Kunde gerade eine Ausleihe aktiv hat. Wenn dies der Fall ist, wird eine Fehlermeldung erzeugt. Ansonsten wird er gelöscht.

Tabellen erzeugen
create table Kunde
(
  Name varchar(100) not null,
  Geburtsdatum date,
  constraint Kunde_PK primary key (Name)
);
--Wohnort aus letztem Beispiel ist hier nicht nötig.

create table DVD 
( 
  asin varchar(20) not null,
  constraint DVD_PK primary key (asin)
);
--Hier müsste eigentlich die Tabelle der Produktion kommen, die auf der DVD enthalten ist!

create table Exemplar 
( 
  nummer int not null,
  asin varchar(20) not null,
  constraint Exemplar_PK primary key (nummer, asin),
  constraint Exemplar_FK1 foreign key (asin) references DVD (asin) on delete cascade
);

create table Verleihvorgang
(
  asin varchar(20) not null,
  nummer int not null,
  kunde varchar(100) not null,
  constraint Verleihvorgang_PK primary key (asin, nummer, kunde),
  constraint Verleihvorgang_FK1 foreign key (asin, nummer) references Exemplar(asin, nummer) on delete restrict,
  constraint Verleihvorgang_FK2 foreign key (kunde) references KUNDE (name) on delete restrict
);

Daten anlegen

insert into DVD (asin) values ('0815');
insert into DVD (asin) values ('4711');

insert into Exemplar (asin, nummer) values ('0815', 1);
insert into Exemplar (asin, nummer) values ('0815', 2);
insert into Exemplar (asin, nummer) values ('4711', 1);
insert into Exemplar (asin, nummer) values ('4711', 2);


insert into Verleihvorgang (asin, nummer, kunde) values ('0815', 2, 'Hans Mustermann');

Funktion für Löschen des Kunden

CREATE or replace FUNCTION KundeLoeschen(varchar)
RETURNS void
AS '
DECLARE
PName ALIAS FOR $1;
zeileVerleih Verleihvorgang%ROWTYPE;
zeileKunde Kunde%ROWTYPE;
BEGIN

--Gibt es den Kunden überhaupt?
select * INTO zeileKunde from Kunde where Name = PName;
IF NOT FOUND THEN
  Raise Exception ''Der Kunde % wurde nicht gefunden!'', PName;
END IF;

SELECT * INTO zeileVerleih FROM Verleihvorgang where Kunde = PName;
IF FOUND THEN
  Raise Exception ''Der Kunde % hat mindestens einen Verleihvorgang'', PName;
END IF;


--Kunde löschen
delete from Kunde where Name = PName;

END;
' LANGUAGE 'plpgsql';

Hinweis: Die Zeile mit der Fehlermeldung sieht eigentlich so aus: "Raise Exception 'Der Kunde % hat mindestens einen Verleihvorgang', PName;"
Da ich im Beispiel das Hochkomma ' als große Klammerung um den Funktionsrumpf benutzt habe, muss ich es beim Erzeugen der Fehlermeldung maskieren durch Verdopplung.
Alternativ findet man in Hr. Krechels Folien und im Web häufig das doppelte "$". Dies klappt allerdings in SquirrelSQL nicht, hier kommt eine Fehlermeldung "Error: FEHLER: Dollar-Quotes nicht abgeschlossen bei »$$
DECLARE
PName ALIAS FOR $1«"
Über "pgadmin3" klappt das Anlegen einer solchen Function allerdings.


Funktion ausführen

select KundeLoeschen ('Hans Mustermann');
select KundeLoeschen ('Evelyn Nichtvorhanden');
select KundeLoeschen ('Gaby Mustermann');
Aufruf 1 wird einen Fehler bringen "Error: FEHLER: Der Kunde Hans Mustermann hat mindestens einen Verleihvorgang". Aufruf 2: "Error: FEHLER: Der Kunde Evelyn Nichtvorhanden wurde nicht gefunden!". Aufruf 3 klappt.

Danach aufräumen:
Beim "drop" müssen die Parametertypen angegeben werden!

drop FUNCTION KundeLoeschen(varchar);
drop table Verleihvorgang;
drop table Exemplar;
drop table DVD;
drop table Kunde;

Beispiel 3: Alter des Kunden

Die folgende Funktion ermittelt das Alter des Kunden in Jahren. Sie nutzt die Tabelle "Kunde" aus Beispiel 1.

Funktion erzeugen
CREATE or replace FUNCTION Alter(varchar)
RETURNS Int
AS '
DECLARE
PName ALIAS FOR $1;
zeileKunde Kunde%ROWTYPE;
BEGIN

--Gibt es den Kunden überhaupt?
select * INTO zeileKunde from Kunde where Name = PName;
IF NOT FOUND THEN
  Raise Exception ''Der Kunde % wurde nicht gefunden!'', PName;
END IF;


return Extract (year from Age(zeileKunde.Geburtsdatum));

END;
' LANGUAGE 'plpgsql';
In den mir bekannten Datenbanken kann man zwei Datumswerte voneinander abziehen und erhält dann z.B. die Differenz in Tagen oder Sekunden. Aber in Postgres gibt es eine spezielle Funktion "Age" für die Differenz von übergebenem Datum und "heute". Diese Funktion gibt ein "interval" zurück, und dessen Komponente "year" wird mittels der Funktion "extract" extrahiert.

Funktion ausführen

select Alter ('Hans Mustermann');
select Alter ('Gaby Mustermann');
select Alter ('Evelyn Invalid');

Danach aufräumen:

drop FUNCTION Alter(varchar);


SquirrelSQL

"SquirrelSQL" ist ein Tool, um Datenbankstatements auszuführen. Dank Nutzung von "JDBC" (Java Database Connectivity) ist dies für alle Datenbanken möglich, die einen JDBC-Treiber anbieten.

Installation

Homepage: http://www.squirrelsql.org/
Download: http://www.squirrelsql.org/#installation (ich empfehle "Plain zip format of SQuirreL 3.3.0")
Danach wird man die SourceForge-Seite weitergeleitet. Hier "squirrel-sql-3.3.0-standard.tar.gz" herunterladen.
Entpacken und "squirrel-sql.bat" (bzw. "squirrel-sql.sh" unter Linux) ausführen.

JDBC-Treiber einrichten

Zuerst benötigen wir den JDBC-Treiber der PostgreSQL: http://jdbc.postgresql.org/download.html
Hier nehmen wir die "Current version: JDBC4 Postgresql Driver, Version 9.1-902" (zu prüfen wäre, ob man für die Nutzung der FH-Datenbank einen JDBC-Treiber benötigt, der kompatibel zu Version 8.4 ist)
Die JAR-Datei "postgresql-9.1-902.jdbc4.jar" legt man irgendwohin.

Jetzt gehen wir in SquirrelSQL auf den Karteireiter "Driver", suchen "PostgreSQL" in der Liste und wählen im Kontextmenü "Modify Driver":
Modify Driver
In dem sich öffenen Dialog gehen wir auf den Karteireiter "Extra Class Path" und fügen über "Add" die eben heruntergeladene JAR-Datei zu.
Extra Class Path

Datenbankverbindung einrichten

Auf dem Karteireiter "Aliases" wählen wir im Kontextmenü "New Alias..." aus:
New Alias

Man wählt den Driver "PostgreSQL" (hat jetzt einen blauen Haken, da wir ihn im vorherigen Schritt eingerichtet hatten).
Im Feld "URL" steht der PostgreSQL-Connectionstring mit einigen Platzhaltern in spitzen Klammern. Diese sind zum Teil optional (z.B. der Port). Den Host und den Zieldatenbanknamen muss man aber auf jeden Fall angeben.
Mehr Details zum Format für eine PostgreSQL-URL: http://jdbc.postgresql.org/documentation/91/connect.html
Benutzername und Passwort sind an dieser Stelle optional, man könnte sie auch bei jedem Verbindungsversuch neu eingeben.
Über den Button "Test" kann man die Verbindung mit den eingegebenen Parametern testen lassen
Add Alias


Will man die Verbindung später aufbauen, wählt man im Kontextmenü "Connect":
Connect

SquirrelSQL verwenden

Jetzt erscheint ein Fenster, in dem man auf dem Karteireiter "SQL" ein großes Eingabefeld findet (muss man sich eventuell erst groß ziehen, ist in der Standardeinstellung ziemlich klein).
Einen eingegebenen SQL-Befehl kann man mittels des Toolbar-Buttons "Run SQL" (im Screenshot markiert) ausführen.
Anmerkung: es wird nur das Statement ausgeführt, auf dem der Cursor gerade steht. Man kann allerdings auch mehrere Befehle markieren und dadurch im Block ausführen lassen.
Run SQL

Blatt 8

Aufgabe 1: "Operatorbaum":
Wie im Praktikum kurz gezeigt, hier ein Beispiel für einen Operatorbaum: http://wikis.gm.fh-koeln.de/wiki_db/Datenbanken/Operatorbaum
(Die Symbole für die Operationen entsprechen nicht komplett Hr. Krechels Vorgaben, vermutlich weil der Zeichensatz der Webseite nicht alle Zeichen enthält und deshalb Ersatz gesucht wurde)
Achtung: Im Praktikum heute habe ich den Baum falsch herum aufgebaut ;-).

Postgres-JOIN-Syntax: http://www.postgresql.org/docs/9.0/static/queries-table-expressions.html


Aufgabe 2: Erklärung der "Teilmenge von"/"Menge von"-Symbole: http://de.wikipedia.org/wiki/Teilmenge
"A ist eine Teilmenge von B ..., wenn jedes Element von A auch in B enthalten ist. Wenn B zudem weitere Elemente enthält, die nicht in A enthalten sind, so ist A eine echte Teilmenge."


Blatt 7

Hr. Krechels Korrekturvorgaben als Leitfaden: KorrekturvorgabenBlatt7.pdf

Hinweise zur Abgabe:

Blatt 5

Beispiellösung aus Studentenkreisen: Blatt5.pdf

Ein paar Infos zu Aufgabe 1:

Für die Lösung gibt es wohl drei Möglichkeiten:

Variante 1: Hülle der Funktionalen Abhängigkeiten
Die Hülle (closure) kann z.B. durch Anwendung der Inferenzregeln berechnet werden. Sind die Hüllen F+ von F und G+ von G identisch, sind die Abhängigkeitsmengen äquivalent.
Siehe z.B. für diese Theorie: http://books.google.de/books?id=REgdRECfcRIC&pg=PA316&lpg=PA316#v=onepage&q&f=false

Und ein konkretes Beispiel für die Hülle: http://web.fhnw.ch/plattformen/edbs/modulunterlagen/RelDesign.pdf (auf Seite 12), leider unkommentiert
Hier ein Beispiel, das die Schritte aufzeigt: http://cis.csuohio.edu/~matos/notes/cis-611/ClassNotes/17-FuncDepend.html

Aus der Aufgabenstellung habe ich mir diese Schritte zusammengereimt, um zu beweisen, dass "AC -> D" aus F in der Hülle von G enthalten ist:

Variante 2: über die Attributhülle
Attributhülle (attribute closure): http://de.wikipedia.org/wiki/Funktionale_Abh%C3%A4ngigkeit#Attributh.C3.BClle
Zitat: "Die Attributehülle (alpha plus) eines bestimmten Attributs ist eine Liste aller Attribute, die von (alpha) funktional abhängen. Im kleinsten Fall ist die Attributhülle nur das Attribut selbst, da keine anderen Attribute von ihm abhängen."

Das Verfahren ist hier erläutert: http://www.scribd.com/doc/3275832/Funktionale-Abhangigkeit (eigentlich eine Nervseite...), Seite 12
Das Vorgehen ist eigentlich nur aus der Formel erkennbar: für jede funktionale Abhängig in F wird die Attributhülle der linken Seite in G ermittelt und geprüft, ob die rechte Seite der funktionalen Abhängigkeit in dieser Attributhülle enthalten ist.
Beispiel für "{A, C} -> {D}" von "F": Attributhülle von "{A, C}" in "G" ist "{A, C, D}". Diese enthält die rechte Seite der Abhängigkeit, nämlich "{D}"

Gilt dies für alle funktionalen Abhängigkeiten von F und G, dann sind die Abhängigkeitsmengen äquivalent.

Dieser Algorithmus ist auch als "RAP-Algorithmus" zu finden, siehe http://www.informatik.tu-cottbus.de/~tk/lehre/DBING_SS04/7_Normalisierung_und_FD.pdf, Seite 15-17 (hier wird nicht die Äquivalenz betrachtet, sondern nur die Frage "ist eine Abhängigkeit X -> Y in der Hülle F+ enthalten?".

Variante 3: über die kanonische Überdeckung
Siehe Aufgabe 2

Hier zusammengefaßt die Zwischenergebnisse:
Schritt 1: Linksreduktion von F ergibt:
Schritt 2: Rechtsreduktion von F ergibt:
Schritt 3: Funktionale Abhängigkeiten mit leerer rechter Seite rauswerfen: haben wir nicht.
Schritt 4: zusammenfassen: Und hiermit haben wir schon die Menge G erhalten! D.h. G ist die kanonische Überdeckung von F.

Umgekehrt müsste man auch von G die kanonische Überdeckung ermitteln, aber hier ist nichts reduzierbar (wie auch, wenn es schon eine kanonische Überdeckung ist ;-)?).


Infos zu Aufgabe 2:

"kanonische Überdeckung": http://de.wikipedia.org/wiki/Kanonische_%C3%9Cberdeckung
Dort finden sich Verweise auf die Algorithmen zur Ermittlung der Kanonischen Überdeckung.
Und zur Erklärung der ganzen Symbole ;-): http://de.wikipedia.org/wiki/Griechisches_Alphabet und http://de.wikipedia.org/wiki/Mathematische_Symbole#Mengenlehre

Definition der kanonischen Überdeckung in "Datenbanksysteme" (Kemper, Eickler):
http://books.google.de/books?id=xpNefMq5nYwC&pg=PA177&lpg=PA177 (Seite 177 ist relevant)

Ein Vorlesungs-PDF, das die Theorien anders formuliert darstellt:
http://greententacle.techfak.uni-bielefeld.de/lehrverwaltung/upload/attachment/1-DB_08_FDs.pdf

Und noch ein PDF, das z.B. die Links-/Rechtsreduktion übersichtlicher darstellt:
http://www.cs.uni-paderborn.de/fileadmin/Informatik/AG-Engels/Lehre/SS09/DaBa/Folien/Kapitel_3_-_Relationaler_Entwurf_-_Teil_5.pdf

Kurzbeschreibung Linksreduktion:
Für jede funktionale Abhängigkeit, die auf der linken Seite mehr als ein Attribut hat, wird geprüft, ob man eines der Attribute reduzieren kann. Dazu ermittelt man die Attributhülle des Rests der linken Seite. Bei "ABC -> D" würde man also erst prüfen, ob man A streichen kann: Attributhülle von "BC" ermitteln. Als Ausgangslage enthält die Attributhüller hier "BC", und dann berechnet man sie nach den bekannten Schritten. Dabei betrachtet man auch die originale funktionale Abhängigkeit "ABC -> D", nicht die reduzierte Variante. Hat man also bereits A, B und C in der Attributhülle, dann kommt durch "ABC -> D" auch D ins Spiel.
Enthält die Attributhülle von "BC" die komplette rechte Seite (hier: "D"), kann man "A" streichen.
Falls man mehr als zwei Attribute auf der linken Seite hat, kann man eventuell mehr als ein Attribut reduzieren. Ich denke es macht Sinn, nach einer erfolgreichen ersten Reduzieren den zweiten Reduzierungslauf mit einer Menge an funktionalen Abhängigkeiten zu starten, die statt der Originalabhängigkeit mit z.B. drei Attributen auf der linken Seite bereits die reduzierte Abhängigkeit enthält.

Kurzbeschreibung Rechtsreduktion:
Für jede funktionale Abhängigkeit (auch solche, die auf der rechten Seite nur ein Attribut hat - bei erfolgreicher Reduktion erhält man hier eine leere Menge), wird geprüft, ob man eines der Attribute reduzieren kann. Dazu ermittelt man die Attributhülle der linken Seite, allerdings aus einer Menge von funktionalen Abhängigkeiten, in der aus der aktuellen Abhängigkeit das gerade betrachtete Attribut der rechten Seite entfernt wurde! Bei "AB -> CD" würde man also erst prüfen, ob man C streichen kann: Attributhülle von "AB" ermitteln. Dabei ersetzt man die originale funktionale Abhängigkeit "AB -> CD" durch die reduzierte Form "AB -> D" (also das, was nach der Reduktion übrig bleibt).
Enthält die Attributhülle von "AB" immer noch den Rest der rechten Seite (als "D"), kann man "C" aus der rechten Seite streichen.
Auch hier prüft man reduzierte funktionalen Abhängigkeit weiter, d.h. im nächsten Schritt würde man prüfen, ob aus "AB -> D" auch das "D" reduzierbar ist.


Blatt 4

Hier eine beispielhafte Lösung eines Studenten: Blatt4.odt


Blatt 3

Bewertung siehe oben.
Hr. Krechels Korrekturvorgaben als Leitfaden: KorrekturvorgabenBlatt3.pdf
Allerdings habe ich daran Änderungen, z.B. möchte ich das Genre als eigene Entität sehen.

Bitte Rückmeldung, wenn euch etwas falsch vorkommt oder ich euch ungerecht behandelt habe!


Ein Hinweis von Hr. Krechel dazu:
Da die zweite Abgabe auf der Ersten aufbauen wird, ist es natürlich wichtig, dass den Studenten ihre Fehler erklärt werden und diese ihre ER-Modelle verbessern. Also nutzt die Zeit bis zur zweiten Abgabe, um euer Modell zu überarbeiten.

In Read.mi stand der Kommentar "Zum Bestehen muss etwas abgegeben werden". Dazu hat Hr. Krechel per Mail etwas gesagt:
Obligatorisch im read.mi bedeutet, dass etwas hochgeladen wird. Man muss jedoch nicht 50% der Punkte erreichen. Da die Abgaben inhaltlich aufeinander aufbauen werden ist es natürlich schwer ein normalisiertes relationales Modell ohne das entsprechende ER-Modell zu erstellen...
Da ich niemanden wegen mehrdeutiger Ansage durch mich jetzt schon aus dem Praktikum rauswerfen will, werde ich Morgen in der Vorlesung festlegen das nur 3 der 4 Abgaben abgegeben werden müssen. Trotzdem muss man bei dreien mindestens 50% der Punkte erreichen ...


Und zur Frage "Werden zum Bestehen die Hälfte von 27 oder die Hälfte von 30 Punkte benötigt?" hat Hr. Krechel geantwortet:
Ich kann mit einem bestanden mit 13,5 Punkten leben auch wenn in der Aufgabenstellung "Die folgenden Angaben beschreiben nur eine Teil der Informationen die diese Datenbank liefern soll. Es ist ihre Aufgabe alle benötigten Information und Funktionen für diese Anwendung zu erarbeiten" stand.



Ein paar Erkenntnisse aus der Fragestunde:

Kardinalitäten in ternären Relationen:
Ein Beispiel ist hier (am Ende der Seite) zu finden: http://bkb-netz1.dynalias.org/grantz/db/entwurf/3eerm/mehrfach.html

Darstellung einer Generalisierung/Spezialisierung:
Siehe http://www.uni-weimar.de/medien/webis/teaching/lecturenotes/databases/unit-de-conceptual-design2.pdf (Seite 89 kapitelübergreifend bzw. innerhalb dieser Datei Seite 33 und folgende): scheinbar ist diese Verbindung zwischen Entitäten nicht Teil des originalen ERM-Diagramms, deshalb gibt es unterschiedliche "Ergänzungsvarianten", darunter auch z.B. ein Sechseck mit dem Inhalt "is-a" (Seite 93/26). Ich bevorzuge die von Hr. Krechel in der Vorlesung verwendete Variante mit der Relation-Raute und dem Inhalt "Ist". Wichtig dabei: in Richtung der Parent-Entität muss eine Pfeilspitze stehen.

Abgabe über "read.mi..."
Mittlerweile ist unter https://read.mi.hs-rm.de die Möglichkeit der Abgabe freigeschaltet. Wer das nicht findet (oder nicht will ;-)), kann auch per Mail an mich abgeben.


Blatt 2

Hier die im Praktikum gezeigte Lösung von Blatt 2, Aufgabe 2: Aus der ersten Gruppe (ab 16 Uhr): Blatt2_Aufgabe2.dia
Bitte beachten: die Verbindung von "Ticket" zu "Flug" ist vermutlich wirklich unnötig.

Aus der zweiten Gruppe (ab 17:45 Uhr): u2ticket.dia


Lokale PostgreSQL unter Windows

Installation

Download: http://www.postgresql.org/download/windows/ bzw. direkt hier: http://www.enterprisedb.com/products-services-training/pgdownload
Ich empfehle die neueste Version (aktuell: 9.1.3).
Es gibt auch einen Download ohne Installer (Zip-Datei), aber hier muss man sich alles selbst einrichten - nicht für den Einstieg geeignet.

Bei der Installation klickt man im Prinzip immer nur auf "Weiter". Einzige Besonderheit: während der Installation wird man aufgefordert, das Passwort für den Benutzer "postgres" (Datenbankbenutzer und gleichzeitig ein lokaler Windows-Benutzer) einzugeben. Dies muss man sich merken, sonst kann man sich später nicht mit der Datenbank verbinden.

Verbinden mit der Datenbank:
Da "psql.exe" den Login des Windows-Benutzers als Default-Datenbankbenutzernamen verwendet (und der mit hoher Wahrscheinlichkeit nicht "postgres" heißt ;-)), muss man den Benutzernamen im Aufruf mitgeben. Hier ein Beispiel für die Verwendung des Standardbenutzers "postgres":
psql.exe --username postgres

Tuning:
Die Datenbank wird jetzt automatisch als Hintergrunddienst gestartet. Ich empfehle, den Datenbank-Dienst auf den Starttyp "Manuell" zu stellen und ihn nur bei Bedarf zu starten und danach wieder zu stoppen.
Postgres-Dienst

Administration

Die lokale Datenbank wird mittels "pgAdmin" verwaltet, zu finden im Startmenü hier:
pgAdmin starten
Hier meldet man sich am lokalen Server an und sieht danach dieses Fenster vor sich:
pgAdmin


Wer will, kann sich hier eine eigene Datenbank und einen neuen Benutzer anlegen (unter anderem, um eine Spielwiese zu haben, oder auch um z.B. andere Zeichensätze zu testen).

Schritt 1: neuer Benutzer:
Neuer Benutzer (1)
Auf dem ersten Karteireiter einen Loginnamen (heißt hier: "Rollename") vergeben und auf dem zweiten Karteireiter "Definition" ein Passwort eintragen:
Neuer Benutzer (2)
Das reicht bereits an Eingaben für einen neuen Benutzer.

Schritt 2: neue Datenbank:
Neue Datenbank (1)
Hier geben wir einen Namen ein und wählen als "Eigentümer" den eben erstellten Benutzer:
Neue Datenbank (2)

Verwenden der Datenbank:
Hier muss der Datenbankname in den "psql"-Argumenten angegeben werden.
psql.exe --dbname=knauftest --username=knauftest


PostgreSQL-Client unter Windows

"psql.exe" ist ein wenig störrisch unter Windows im Bezug auf Umlaute.
Das zeigt sich schon beim Start, wo solch eine Meldung ausgegeben wird:
Warning: Console code page (850) differs from Windows code page (1252)
         8-bit characters might not work correctly. See psql reference
         page "Notes for Windows users" for details.

"cmd.exe" konfigurieren

Hauptursache ist, dass die Windows-Kommandozeile einen uralten Zeichensatz (eben die CodePage "850", http://de.wikipedia.org/wiki/Codepage_850 ) verwendet.

Welche Codepage gerade aktuell ist, sieht man über den Befehl "chcp" ohne Parameter:
C:\...\...>chcp
Aktive Codepage: 850.

Schritt 1 ist deshalb, dies umzustellen auf Codepage "1252" (Default-Zeichensatz für alle westeuropäischen Windowsversionen)
C:\...\...>chcp 1252
Aktive Codepage: 1252.

Das macht die Lage aber erstmal eher schlimmer - jetzt werden sogar eingegebene Umlaute falsch dargestellt ;-).
Deshalb in Schritt die Konsolen-Schriftart umstellen: Im Fenstermenü (Fenstericon anklicken) auf "Eigenschaften" gehen:
Fenstermenü
Die Schriftart von "Rasterschriftart" auf "Lucida Console" ändern:
Lucida Console
Jetzt stimmen die eingebenen Umlaute wieder, und auch "psql.exe"-Ausgaben sind korrekt.

Falls man sich versehentlich das gesamte System umgestellt hat (auf meinem Privatrechner kam eine Abfrage "nur für aktuelles Fenster oder für alle?", unter Windows 7 an der FH scheint die Schriftartänderung aber für alle Konsolen zu gelten), hier ein Screenshot der Originaldaten ("Rasterschriftart" der Größe "8x12"):
Originalzustand


Encoding in "psql.exe"

Auf meinem Privatrechner mit PostgreSQL 9.1 als lokalem Server konnte ich ab hier frei arbeiten. An der FH (Clientversion 8.3) kam allerdings bei Verwendung von Umlauten z.B. in SELECT-Statements folgenden Fehlermeldung:
FEHLER:  ungültige Byte-Sequenz für Kodierung »UTF8«: 0xf6e4fc27
Ursache ist hier, dass "psql.exe" nicht das gleiche Encoding wie die Kommandozeile verwendet. Um das aktuelle Encoding herauszufinden:
datenbankname=> show client_encoding;
 client_encoding
-----------------
 UTF8
(1 Zeile)
Dies ist eine Beispielausgabe von der FH. Wenn hier "WIN1252" steht, sollten Umlaute klappen. UTF8 allerdings sollte umgestellt werden:
datenbankname=> SET client_encoding TO 'win1252';
SET
Jetzt können wir ein Beispielselect abfeuern:
select 'öäüÖÄÜß';
Kommen die Umlaute hier korrekt heraus, scheint alles OK zu sein.



Nur zur Info: in welchem Encoding die Datenbank auf dem Server liegt, findet man so heraus (Spalte "Kodierung" des Ergebnisses):

knauftest=> \l
                                         Liste der Datenbanken
   Name    | Eigentümer | Kodierung |    Sortierfolge     |     Zeichentyp
|  Zugriffsprivilegien
-----------+------------+-----------+---------------------+---------------------
+-----------------------
 knauftest | knauf      | UTF8      | German_Germany.1252 | German_Germany.1252
|
 postgres  | postgres   | UTF8      | German_Germany.1252 | German_Germany.1252
|
 template0 | postgres   | UTF8      | German_Germany.1252 | German_Germany.1252
| =c/postgres          +
           |            |           |                     |
| postgres=CTc/postgres
 template1 | postgres   | UTF8      | German_Germany.1252 | German_Germany.1252
| =c/postgres          +
           |            |           |                     |
| postgres=CTc/postgres
(4 Zeilen)

Weitere Informationen: http://www.commandprompt.com/ppbook/c12119


"Echtes" UTF8 auf Clientseite

Theoretisch sollte es reichen, die Codepage der Kommandozeile auf "65001" zu setzen ( http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx ). Aber danach rastet psql.exe total aus und spuckt bei fast jeder Aktion Fehler "Nicht genügend Arbeitsspeicher." aus. Das Web liefert leider viele Treffer zu dieser Meldung, aber keine Lösung.


Encoding in Scripten

Sollen mit dem psql-Befehl "\i" Scripte aus Dateien ausgeführt werden, wird zum Einlesen dieser Datei wohl aktuell in psql eingestellte Kodierung verwendet. Das kann Probleme bei Sonderzeichen machen. Deshalb sollte man beim Generieren der Scriptdatei darauf achten, unter welchem Encoding man sie speichert. Der Windows-Editor (Notepad) zum Beispiel bietet im "Speichern unter"-Dialog eine Combobox mit einigen verfügbaren Encodings an. Unter Windows Vista/Windows 7 ist hier per Default "UTF-8" gewählt. Hat man die Konsole (wie oben beschrieben) auf "Windows1252" umgestellt, sollte man die Scripte als "ANSI" speichern:
Dateiencoding
Als "schlechtes" Beispiel sei hier die Scriptdatei von Hr. Krechel ("u1a3.sql") genannt, die im UTF8-Format vorliegt ;-). Hier geht zum Glück nichts kaputt, aber einige Kommentare enthalten Umlaute und werden falsch ausgegeben.



Stand 10.07.2012
Historie:
21.03.2012: Erstellt
25.03.2012: Postgres-Installation
04.04.2012: Beispiellösung Blatt 2, Aufgabe 2
10.04.2012: Fragestunde 11.4.
11.04.2012: Infos zu Blatt 3
24.04.2012: Bewertung Blatt 3
25.04.2012: Beispiellösung Blatt 4, Links zu Blatt 5
25.04.2012: Ergänzung zur Bewertung
01.05.2012: Weiterer Link zur kanonischen Überdeckung
04.05.2012: Blatt 5 Aufgabe 1: Äquivalenz überarbeitet
10.05.2012: Blatt 5 Aufgabe 1: Lösung für kanonische Überdeckung, mehr Anleitung zur kanonischen Überdeckung
16.05.2012: Hinweise zu Blatt 7
19.05.2012: Beispiellösung Blatt 5
20.05.2012: Beispiellösung Blatt 5 aktualisiert
23.05.2012: Blatt 5: Link zu Mengenlehre-Symbolen verbessert, Infos zu Blatt 8
30.05.2012: Blatt 8: Link zu Operatorbaum und zu Postgres-JOIN-Syntax
11.06.2012: Evaluationsergebnis, SquirrelSQL
16.06.2012: Bewertung Blatt 7: meine Kritikpunkte
20.06.2012: Update Bewertungskriterien Blatt 7, Hinweise Blatt 10
21.06.2012: Funktions-Beispiele für Blatt 10
25.06.2012: Bewertung Blatt 7
28.06.2012: Hinweise Blatt 11, Musterlösung des Rests von Blatt 9, Korrektur einer falschen Matrikelnummer in Bewertung.
04.07.2012: Kritikpunkte zu Blatt 10
09.07.2012: weiteres "nice to have" zu Blatt 11
10.07.2012: Bewertung Blatt 10