WM-Tippspiel Projektdokumentation 14. Juli 2006 Julius Dannert (3982265) David Iwanowitsch (3996430) Florian Thiemer (3992455) Tutor: Yark Schröder Accountnummer: 84 Inhaltsverzeichnis Teil 1: Allgemeine Projektbeschreibung............................................................................... 3 Teilnehmer....................................................................................................................... 3 Tippgemeinschaft............................................................................................................. 3 Punktevergabe................................................................................................................. 3 Adminaccount.................................................................................................................. 3 Tei 1b: ER-Diagramm zum WM-Tippspiel............................................................................ 4 Kommentare zum ER-Diagramm..................................................................................... 5 Teil 1a: Geschäftsprozessbeschreibung.............................................................................. 6 Teil 2: Relationales Schema............................................................................................... 11 1. Schritt......................................................................................................................... 11 2. Schritt......................................................................................................................... 11 Teil 3: Relationen in PostgreS............................................................................................ 12 Tabellenbeschreibung.................................................................................................... 12 Datenmodifikationskommandos..................................................................................... 13 Teil 4: Datenbasen............................................................................................................. 14 Teil 5: SQL-Anfragen.......................................................................................................... 14 Datenmodifikations-Kommandos................................................................................... 18 Teil 6: Views....................................................................................................................... 18 Teil 7: Webanbindung der Datenbank................................................................................ 19 Teil 8: Indexierung.............................................................................................................. 19 Teil 9: Transaktionen.......................................................................................................... 20 a) Ausführen einer Transaktion ..................................................................................... 20 b) Abbrechen einer Transaktion .................................................................................... 21 Projektbericht .................................................................................................................... 22 Teil 1: Allgemeine Projektbeschreibung Teilnehmer Jeder Teilnehmer des WM-Tippspiels muss sich einen Account anlegen. Über den Teilnehmer werden dabei Vorname, Nachname, Nickname, Geschlecht, Passwort sowie die E-Mail-Adresse gespeichert. Der Nickname ist eindeutig. Jeder Teilnehmer kann sich über ein Web-Interface anmelden. Er meldet sich mit seinem Nicknamen und seinem Passswort an. Jeder Teilnehmer kann pro WM-Spiel maximal einen Tipp abgeben. Der Tipp kann zeitlich gesehen zwischen dem Bekanntwerden der Begegnungsteilnehmer und dem Anpfiff abgegeben und geändert werden. Änderungen nach dem Anpfiff sind logischerweise nicht erlaubt. Zu jedem Spiel kann der Teilnehmer Informationen abrufen, um seinen Tipp besser abschätzen zu können. Die Informationen beinhalten neben den Teilnehmenden Mannschaften, das Stadion sowie den Zeitpunkt des Anpfiffes. Für bereits beendete Spiele wird desweiteren das Ergebnis angezeigt. Außerdem kann man sich für eine Mannschaft die bisherigen Spielergebnisse der WM, sowie einen Infotext anzeigen lassen. Tippgemeinschaft Des weiteren können Tippgemeinschaften mit bis zu vier Mitgliedern gegründet werden. Jeder Teilnehmer kann in maximal einer Tippgemeinschaft sein. Jeder Teilnehmer kann einer bestehenden Tippgemeinschaft beitreten oder seine eigene gründen. Will ein Spieler einer Tippgemeinschaft beitreten, so muss der Gründer zustimmen. Ein Spieler kann die Tippgemeinschaft auch wieder verlassen. Verlässt der Gründer die Tippgemeinschaft so wird die Tippgemeinschaft aufgelöst. Jede Tippgemeinschaft hat einen eindeutigen Namen. Punktevergabe Jeder Teilnehmer kann zu jeder Zeit seinen aktuellen Punktestand, sowie den Punktestand seiner Tippgemeinschaft abrufen. Des weiteren kann er eine Top-Tabelle der besten Tipper und der besten Tippgemeinschaften abrufen. Ein Spieler bekommt für einen Volltreffer, d.h. der Spielstand wurde richtig getippt, 5 Punkte. Hat er die Tordifferenz richtig getippt, dann bekommt er 3 Punkte. Hat er nur den Sieger richtig getippt, bekommt er 2 Punkte. Sollte nicht die Mannschaft gewinnen auf die er getippt hat, so bekommt er 0 Punkte. Adminaccount Es gibt einen Adminaccount, über den der Admin die Ergebnisse der Begegnungen eingeben kann. Über den Adminaccount werden ebenfalls sämtliche Spiele angelegt. Des weiteren können über den Adminaccount die Gruppen und ihre Mannschaften (inkl. Infotext) angelegt werden, außerdem können zu jedem Spiel zusätzliche Informationen eingegeben werden. Tei 1b: ER-Diagramm zum WM-Tippspiel Kommentare zum ER-Diagramm Das Diagramm hat folgende Entitäten: 1. Den Benutzer, der den User verkörpert, der Tipps auf Fußballspiele abgibt und mit anderen Spielern in einer Tippgemeinschaft sein kann. Bei jedem Tipp kann er Punkte erhalten. 2. Die Tippgemeinschaft, zu der sich Benutzer bewerben können und die nach einer Annahme zu der Gemeinschaft gehören können. 3. Das Spiel, auf das jeder Benutzer einen Tipp abgeben darf, in jedem Spiel spielen eine erste und eine zweite Mannschaft gegeneinander, außerdem ist jedes Spiel teil der aktuellen Spielart. 4. Die Mannschaft, sie trägt als erste oder zweite Mannschaft ein Spiel gegen die jeweils andere Mannschaft aus und kann dabei Tore erzielen. 5. Das Stadion, in ihm finden Spiele statt. Es hat einen eindeutigen Namen und eine bestimmte Anzahl von Plätzen. Die Punkte, die ein Spieler für einen Tipp bekommt, werden direkt für diesen Tipp eingetragen, und nicht auf eine Gesamtpunkteliste addiert, da es auf diese Weise sehr viel leichter ist, nachträglich die Punkte zu korrigieren, zum Beispiel, wenn ein Admin ein falsches Ergebnis eingetragen hat und dies korrigieren will. Mannschaften nehmen als erste und zweite Mannschaft an einem Spiel teil, um so zu gewährleisten, dass es eindeutig ist, welche Mannschaft beim Ergebnis zuerst genannt wird. Spiele gehören zu einer Spielart um so die Ausgabe übersichtlicher zu gestalten. Die Spielart meint die aktuelle Runde, also Vorrunde, Achtelfinale usw. Jedes Fußballspiel hat eine eindeutige SpielID , damit ein Spiel eindeutig identifiziert werden kann und es zu keinerlei Uneindeutigkeiten kommen kann. Teil 1a: Geschäftsprozessbeschreibung Geschäftsprozess: Login Ziel: Der User möchte sich in das System einloggen. Akteur: User Eingabe: Nickname und Passwort Result: Der User hat sich eingeloggt. Ausnahme: Der User hat eine falschen Usernamen und/oder Passwort eingegeben und wird aufgefordert seine Eingabe zu wiederholen. Geschäftsprozess: Registrierung Ziel: Erstellung eines Useraccounts Akteur: Unregistrierter User Eingabe: Nickname, Passwort, Vorname, Nachname, E-Mail und Geschlecht Result: Ein neuer Account mit den obrigen Eingaben wurde erstellt. Ausnahme: Der Nickname existiert schon und/oder das Passwort ist kürzer als 3 Zeichen. Es wurde ein ungültiger Vor-/Nachname bzw E-Mail-Addresse eingegeben und wird aufgefordert die Eingaben zu korrigieren. Geschäftsprozess: Erstellen einer Tippgemeinschaft Ziel: Der User möchte eine Tippgemeinschaft gründen, in der er automatisch Mitglied ist. Akteur: eingeloggter User, der bis jetzt in keiner Tippgemeinschaft ist. Eingabe: Name der Tippgemeinschaft. Result: Der User hat eine neue Tippgemeinschaft gegründet und ist Mitglied dieser Tippgemeinschaft. Ausnahme: Der User hat einen bereits existierenden Namen für eine Tippgemeinschaft eingegeben. Er wird zur Eingabe eines anderen Namens aufgefordert. Geschäftsprozess: Bewerbung für eine Mitgliedschaft in einer Tippgemeinschaft. Ziel: Der User möchte in eine Tippgemeinschaft eintreten. Akteur: eingeloggter User, der bis jetzt in keiner Tippgemeinschaft ist. Eingabe: Name der existierenden Tippgemeinschaft. Result: Der User hat sich beworben um in eine Tippgemeinschaft zu kommen. Der Gründer der betreffenden Tippgemeinschaft muss der Bewerbung zustimmen oder sie ablehnen. Ausnahme: Der User hat sich für eine Tippgemeinschaft beworben, die schon 4 Mitglieder hat. Der User kann sich für diese Tippgemeinschaft nicht bewerben. Geschäftsprozess: Bewerbung für eine Mitgliedschaft in einer Tippgemeinschaft beantworten. Ziel: Der Gründer der Tippgemeinschaft beantwortet eine offene Bewerbung für die Mitgliedschaft in seiner Tippgemeinschaft. Akteur: eingeloggter User, der Gründer einer Tippgemeinschaft ist für die Bewerbungen vorliegen. Eingabe: Zustimmung oder Ablehnung als XOR-Entscheidung. Result: Falls zugestimmt wurde ist der Bewerber nun Mitglied der Tippgemeinschaft. Andernfalls wird ihm mitgeteilt, dass seine Bewerbung abgelehnt wurde. Wenn durch eine Zustimmung die Mitgliederanzahl 4 erreicht, werden alle anderen Bewerbungen abgelehnt. Ausnahme: Geschäftsprozess: Austreten aus einer Tippgemeinschaft. Ziel: Der User will aus seiner Tippgemeinschaft austreten. Akteur: eingeloggter User, der Mitglied einer Tippgemeinschaft ist. Eingabe: Bestätigung des Austrittswunsches (aus Sicherheitsgründen) Result: Falls bestätigt wurde ist der User nun nicht mehr Mitglied der Tippgemeinschaft. Ausnahme: Geschäftsprozess: Auflösung einer Tippgemeinschaft Ziel: Der Gründer der Tippgemeinschaft will seine Tippgemeinschaft auflösen. Akteur: eingeloggter User, der Gründer einer Tippgemeinschaft ist. Eingabe: Bestätigung des Auflösungswunsches (aus Sicherheitsgründen) Result: Falls bestätigt wurde werden alle Mitglieder inklusive des Gründers, aus der Tippgemeinschaft entfernt, alle Bewerbungen für die Tippgemeinschaft werden abgelehnt. Der Name der Tippgemeinschaft kann wieder verwendet werden. Ausnahme: Geschäftsprozess: Abgeben eines Spieltipps Ziel: Der User will für ein Fußballspiel einen Tipp abgeben. Akteur: eingeloggter User Eingabe: auswählen des Fußballspiels und sein Tipp(Bsp: Deutschland-Holland : 10:0). Result: Der Tipp wird abgespeichert. Ausnahme: Das Spiel hat bereits begonnen oder ist abgelaufen , dann kann kein Tipp abgegeben werden. Geschäftsprozess: Ändern eines Spieltipps Ziel: Der User will für ein Fußballspiel seinen Tipp ändern. Akteur: eingeloggter User der bereits einen Tip für das Spiel abgegeben hat. Eingabe: auswählen des Fußballspiels und sein Tipp(Bsp: Deutschland-Holland : 10:0). Result: Der neue Tipp wird abgespeichert. Ausnahme: Das Spiel hat bereits begonnen oder ist abgelaufen , dann kann kein Tipp geändert werden. Geschäftsprozess: Anlegen einer WM-Mannschaft Ziel: Der Admin will eine Fußballmannschaft anlegen. Akteur: eingeloggter Admin Eingabe: Land, Informationenstext und die Vorrundengruppe. Result: Die Fußballmannschaft wird angelegt. Ausnahme: Eine Mannschaft für das Land existiert bereits oder es wird eine unsinnige Gruppenbezeischnung eingegeben. Der Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Eingeben eines Spielergebnisses Ziel: Der Admin will ein Spielergebnis eines beendeten Spiels eintragen. Akteur: eingeloggter Admin Eingabe: Spiel, Spielergebnis. Result: Das Spielergebnis wird eingetragen. Für alle Tipps auf dieses Spiel werden die Punkte für die Spieltipps berechnet und eingetragen. Ausnahme: Es wird ein unsinniges Spielergebnis eingetragen oder das Spiel existiert gar nicht. Der Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Ändern eines Spielergebnisses Ziel: Der Admin will ein fehlerhaftes Spielergebnis eines beendeten Spiels ändern. Akteur: eingeloggter Admin Eingabe: Spiel, Spielergebnis. Result: Das Spielergebnis wird geändert. Für alle Tipps auf dieses Spiel werden die Punkte für die Spieltipps neu berechnet und geändert. Ausnahme: Für das Spiel wurde noch gar kein Ergebnis eingetragen. Der Geschäftsprozess „Eingabe eines Spielergebnisses“ wird eingeleitet. Es wird ein unsinniges Spielergebnis eingetragen oder das Spiel existiert gar nicht. Der Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Anlegen eines Fußballspiels Ziel: Der Admin will ein Fußballspiel anlegen. Akteur: eingeloggter Admin Eingabe: Beginn des Spiels (Datum und Uhrzeit), Stadionname, Infotext, 1.Mannschaft und die 2.Mannschaft sowie die Spielart (Mögliche Eingaben: Vorrundenspiel, Achtelfinale, Viertelfinale, Halbfinale, Semifinale, Finale). Result: Das Spiel wird angelegt und erhält eine eindeutige SpielID zugewiesen. Ausnahme: Fehlerhafte Eingabe. Der Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Editieren eines Fußballspiels Ziel: Der Admin will ein fehlerhaft angelegtes Fußballspiel editieren. Akteur: eingeloggter Admin Eingabe: Beginn des Spiels (Datum und Uhrzeit), Stadionname, Infotext, 1.Mannschaft und die 2.Mannschaft sowie die Spielart (Mögliche Eingaben: Vorrundenspiel, Achtelfinale, Viertelfinale, Halbfinale, Semifinale, Finale). Result: Das Spiel wird editiert. Ausnahme: Das Spiel ist bereits abgelaufen. Es ist nur noch eine Editierung des Infotextes möglich.Fehlerhafte Eingabe. Der Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Löschen eines Fußballspiels Ziel: Der Admin will ein versehentlich angelegtes Fußballspiel löschen. Akteur: eingeloggter Admin Eingabe: Das zu löschende Fußballspiel. Result: Das Spiel wird gelöscht, sowie alle evtl. bereits abgegebenen Tipps auf dieses Spiel. Ausnahme: Es gibt kein Spiel zwischen den beiden Mannschaften, der Admin wird zur erneuten Eingabe der Mannschaften aufgefordert. Geschäftsprozess: Anmelden als Admin Ziel: Ein nichteingeloggte Admin möchte sich einloggen. Akteur: nicht eingeloggter Admin Eingabe: Adminname,Adminpasswort. Result: Der Admin ist eingeloggt. Ausnahme: Adminname existiert nicht oder das Passwort ist falsch, der nichteingeloggte Admin wird zur erneuten Eingabe aufgefordert. Geschäftsprozess: Ausloggen als Admin Ziel: Der Admin möchte sich ausloggen. Akteur: eingeloggter Admin Eingabe: Result: Der Admin ist ausgeloggt. Ausnahme: Geschäftsprozess: Abrufen des eigenen Punktestandes Ziel: Der User möchte seinen Punktestand erfahren. Akteur: eingeloggter User Eingabe: Result: Der aktuelle Punktestand wird angezeigt. Ausnahme: Geschäftsprozess: Abrufen des Tippgemeinschaftpunktestandes Ziel: Der User möchte den Punktestand seiner Tippgemeinschaft erfahren. Akteur: eingeloggter User, der Mitglied in einer Tippgemeinschaft ist. Eingabe: Result: Der aktuelle Punktestand wird angezeigt. Ausnahme: Geschäftsprozess: Abrufen der Top-Liste(User) Ziel: Der User möchte die Top-Liste der User mit den meisten Punkten abrufen. Akteur: eingeloggter User. Eingabe: Result: Es wird eine Liste der besten User angezeigt. Wenn es n-viele User mit der gleichen Punktzahl gibt, so werden diese unter der gleichen Platznummer geführt. Der User mit der nächstkleineren Punktezahl hat eine Platznummer die um n+1 höher ist. Es werden maximal 25 User angezeigt. Ausnahme: Geschäftsprozess: Abrufen der Top-Liste(Tippgemeinschaft) Ziel: Der User möchte die Top-Liste der Tippgemeinschaften mit den meisten Punkten abrufen. Akteur: eingeloggter User. Eingabe: Result: Es wird eine Liste der besten Tippgemeinschaften angezeigt. Wenn es n-viele Tippgemeinschaften mit der gleichen Punktzahl gibt, so werden diese unter der gleichen Platznummer geführt. Die Tippgemeinschaften mit der nächstkleineren Punktezahl hat eine Platznummer die um n+1 höher ist. Es werden maximal 25 Tippgemeinschaften angezeigt. Ausnahme: Geschäftsprozess: Ausloggen als User Ziel: Der eingeloggte User möchte sich ausloggen. Akteur: eingeloggter User. Eingabe: Result: Der User ist ausgeloggt. Ausnahme: Geschäftsprozess: Abrufen der Mannschaftsinfos Ziel: Der User möchte die Mannschaftinfos aufrufen. Akteur: eingeloggter User. Eingabe: Mannschaft. Result: Es wird der Mannschaftinfotext angezeigt, sowie die bisherigen Spielergebnisse der Mannschaft. Ausnahme: Die Mannschaft existiert nicht, der User wird zur erneuten Eingabe der Mannschaft aufgefordert. Geschäftsprozess: Editieren eines Infotextes einer Mannschaft Ziel: Der Admin möchte den Infotext einer Mannschaft ändern. Akteur: eingeloggter Admin. Eingabe: Mannschaft, neuer Infotext. Result: Der neue Infotext wird für die Mannschaft gespeichert. Ausnahme: Die Mannschaft existiert nicht, der Admin wird zur erneuten Eingabe der Mannschaft aufgefordert sein neuer Infotext bleibt allerdings erhalten. Geschäftsprozess: Abrufen aller bisherigen Spielergebnisse Ziel: Der User möchte die Spielergebnisse aller Mannschaften abrufen. Akteur: eingeloggter User. Eingabe: Result: Die Spielergebnisse aller Mannschaften sortiert nach Datum. Ausnahme: Geschäftsprozess: Abrufen der Fußballspielinformation. Ziel: Der User möchte die Fußballspielinformation abrufen. Akteur: eingeloggter User. Eingabe: Fußballspiel. Result: Begin, Austragungsort, Datum, Infotext, Spielart, Mannschaft 1 und Mannschaft 2. Ausnahme: Das Fußballspiel existiert nicht, der User wird zur erneuten Eingabe des Fußballspiels aufgefordert. Teil 2: Relationales Schema 1. Schritt Benutzer(Nickname, Vorname, Nachname, Passwort, Email, Geschlecht) Tippgemeinschaft(Name, Gründer, Infotext) Spiel(SpielID, Begin, Infotext, Spielart) Mannschaft(Name, Infotext, Vorrundengruppe) Stadion(Name, Plaetze, Infotext) findet_statt(SpielID, Satdion) spielen(Mannschaft_1, Mannschaft_2, SpielID, Tore_1, Tore_2) tippt(SpielID, Nickname, Tipp_Tore_1, Tipp_Tore_2, Punkte) ist_in(Nickname, Tippgemeinschaftsname) bewirbt(Nickname, Gemeinschaft, is_abgelehnt) 2. Schritt Benutzer(Nickname, Vorname, Nachname, Passwort, Email, Geschlecht, Tippgemeinschaft) Tippgemeinschaft(Name, Gründer, Infotext) Spiel(SpielID, Begin, Stadion, Mannschaft_1, Mannschaft_2, Tore_1, Tore_2, Infotext, Spielart) Stadion(Name, Plaetze, Infotext) Mannschaft(Land, Infotext, Vorrundengruppe) tippt(SpielID, Nickname, Tipp_Tore_1, Tipp_Tore_2, Punkte) bewirbt(Nickname, Gemeinschaft, ist_abgelehnt) Teil 3: Relationen in PostgreS NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "benutzer_pkey" for table "benutzer" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tippgemeinschaft_pkey" for table "tippgemeinschaft" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "mannschaft_pkey" for table "mannschaft" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "stadion_pkey" for table "stadion" NOTICE: CREATE TABLE will create implicit sequence "spiel_spielid_seq" for serial column "spiel.spielid" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "spiel_pkey" for table "spiel" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pk" for table "tippt" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "primary_key" for table "bewirbt" Abfrage war erfolgreich nach 1297 ms. Keine Zeilen geliefert. Tabellenbeschreibung In der Tabelle benutzer wird der Nickname, Vorname, Nachname, Passwort, Geschlecht, Email und die Tippgemeinschaft gespeichert. Der Primärschlüssel ist der Nickname. Es dürfen keine 2 Benutzer mit den gleichen Nicknamen existieren. Beim Geschlecht kann man nur 'M' oder 'W' für männlich bzw. weiblich eintragen. Der Eintrag Tippgemeinschaft ist ein Fremdschlüssel aus der Tabelle tippgemeinschaft die im folgenden angelegt wird. In der Tabelle tippgemeinschaft wird der Name, Gründer und ein Infotext gespeichert. Der Name ist der Primärschlüssel, da es keine 2 Tippgemeinschaften mit dem gleichen Namen geben kann. Der Eintrag Gründer ist ein Fremdschlüssel aus der Tabelle benutzer. In der Tabelle mannschaft wird der Name, Vorrundengruppe und ein infotext gespeichert. Der Name der Fußballmannschaft ist das Land aus dem die Mannschaft kommt. Der Name ist der Primärschlüssel. Die Vorrundengruppe ist ein Großbuchstabe von 'A' – 'H' . In der Tabelle stadion wird der Name, infotext und plaetze gespeichert. Der Name ist die Stadt in der das Stadion steht. Der Name ist der Primärschlüssel. Plaetze gibt an, wieviele Zuschauer in dem Stadion sitzen können. In der Tabelle spiel wird die spielid, begin, stadion, infotext, spielart, mannschaft_1, mannschaft_2, tore_1 und tore_2 gespeichert. Die spielid ist der Primärschlüssel und wird fortlaufend durchnummeriert. Der Eintrag stadion ist ein Fremdschlüssel aus der Tabelle stadion. Die spielart gibt an ob das Spiel aus der Vorrundengruppe, Achtelfinale, Viertelfinale, Halbfinale, Semifinale oder Finale ist. Der Eintrag mannschaft_1 und mannschaft_2 ist jeweils ein Fremdschlüssel aus der Tabelle mannschaft um zu identifizieren welche Mannschaften gegeneinander spielen. Der Eintrag tore_1 und tore_2 gibt an wieviele Tore die jeweilige Mannschaft geschossen hat. Der default Wert ist NULL. Der Admin trägt später die geschossenen Tore ein. In der Tabelle tippt wird der nickname, spielid, tipp_tore_1, tipp_tore_2 und punkte gespeichert. Der nickname ist ein Fremdschlüssel aus der Tabelle benutzer. Der Eintrag spielid ist ein Fremdschlüssel aus der Tabelle spiel. Der nickname und spielid sind zusammen der Primärschlüssel. Im Eintrag punkte wird Anzahl der Punkte für diesen Tipp gespeichert. Der default Wert ist null und wird erst berechnet, nachdem der Admin für dieses Spiel die Tore einträgt. In der Tabelle bewirbt wird der nickname, gemeinschaft und ist_abgelehnt gespeichert. Der Eintrag nickname ist ein Fremdschlüssel aus der Tabelle benutzer. Der Eintrag gemeinschaft ist ein Fremdschlüssel aus der Tabelle tippgemeinschaft. Die Einträge gemeinschaft und nickname bilden zusammen den Primärschlüssel. Der Eintrag ist_abgelehnt hat den default Wert NULL, was bedeutet, dass der Gründer der Tippgemeinschaft noch nicht zugestimmt oder abgelehnt hat. Wird diese Bewerbung abgelehnt, so wird er auf true gesetzt, anbdernfalls auf false. Datenmodifikationskommandos INSERT INTO benutzer (nickname, vorname, nachname, passwort, geschlecht) VALUES ('FLO','Florian','Thiemer','1234','M'); INSERT INTO benutzer (nickname, vorname, nachname, passwort, geschlecht) VALUES ('DAVID','David','Iwanowitsch','1122','M'); INSERT INTO benutzer (nickname, vorname, nachname, passwort, geschlecht) VALUES ('FLO','Julius','Dannert','5678','M'); ERROR: duplicate key violates unique constraint "benutzer_pkey" UPDATE benutzer SET nickname='FLO' WHERE nickname = 'DAVID'; ERROR: duplicate key violates unique constraint "benutzer_pkey" INSERT INTO tippgemeinschaft (name, gruender) VALUES ('meine_tippgemeinschaft','JULIUS'); ERROR: insert or update on table "tippgemeinschaft" violates foreign key constraint "gruender_existiert" DETAIL: Key (gruender)=(JULIUS) is not present in table "benutzer". INSERT INTO tippgemeinschaft (name,gruender) VALUES ('meine_tippgemeinschaft','FLO'); UPDATE tippgemeinschaft SET gruender = 'JULIUS' WHERE name = 'meine_tippgemeinschaft'; ERROR: insert or update on table "tippgemeinschaft" violates foreign key constraint "gruender_existiert" DETAIL: Key (gruender)=(JULIUS) is not present in table "benutzer". INSERT INTO benutzer(nickname, vorname, nachname, passwort, geschlecht) VALUES ('Dummy', 'Hans', 'Wurst', '[email protected]','A'); ERROR: new row for relation "benutzer" violates check constraint "geschlecht_ok" UPDATE mannschaft SET vorrundengruppe = 'X' WHERE name = 'Deutschland'; ERROR: new row for relation "mannschaft" violates check constraint "vorrundengruppe_ok" Teil 4: Datenbasen Programmcode in der Mail enthalten, sowie die SQL Dateien mit den großen Datensätzen. Zuerst die Tabellen anlegen mit create_tables.sql. Anschließend die SQL Dateien in folgender Reihenfolge ausführen: ● ● ● ● ● ● ● ● benutzer.sql mannschaft.sql stadion.sql spiel.sql tippt.sql tippgemeinschaft.sql update_benutzer.sql bewirbt.sql Teil 5: SQL-Anfragen Topliste der Benutzer mit Punkten, die schon mindestens einen Tipp abgegeben haben SELECT t.nickname, sum(t.punkte) as punkte FROM tippt t, benutzer b WHERE b.nickname = t.nickname GROUP BY t.nickname ORDER BY punkte DESC; Nickname Punkte "viapiltj" "17" "lylalhso" "16" "fixobuhs" "16" "chkhvski" "14" "nnburcxj" "14" "fyoahfdt" "13" "hpuooruw" ...... "12" Gesamtlaufzeit der Abfrage: 172 ms. Benötigte Zeit zum Holen der Daten:31 ms. 189 Zeilen geholt. Mannschaften die gegen bouitdbohidfdlcjwdvi spielen, sowie die Spielid, spielart und spielbegin SELECT s.spielid ,m.name, s.spielart, s.begin FROM mannschaft m, spiel s WHERE ((s.mannschaft_1 = m.name AND s.mannschaft_2 = 'bouitdbohidfdlcjwdvi') OR (s.mannschaft_1 ='bouitdbohidfdlcjwdvi' AND s.mannschaft_2 = m.name)) ORDER BY s.begin; Spielid Mannschaft Spielart Begin "67" "fdrguvbdlaswfddixci "Semifinale" g" "2006-06-01 16:00:00" "88" "fsximqfbcrpbxljxqqm "Semifinale" i" "2006-06-11 17:00:00" "85" "hsouitbvvrfdojmtgm md" "2006-06-11 18:00:00" "53" "yfrnguyfbnnmvkslyk "Halbfinale" kh" "2006-06-11 18:00:00" "76" "fjfgbrbrjfqkyuboqcxk "Achtelfinale" " "2006-06-21 17:00:00" "Vorrundengruppe" Gesamtlaufzeit der Abfrage: 531 ms. Benötigte Zeit zum Holen der Daten:0 ms. 5 Zeilen geholt. Benutzer die getippt haben, dass bouitdbohidfdlcjwdvi mindestens ein Spiel gewinnt SELECT b.nickname, b.vorname, b.nachname FROM benutzer b WHERE EXISTS (SELECT * FROM tippt t, spiel s WHERE b.nickname = t.nickname AND s.spielid = t.spielid AND ((s.mannschaft_1 = 'bouitdbohidfdlcjwdvi' AND t.tipp_tore_1 > t.tipp_tore_2) OR (s.mannschaft_2 = 'bouitdbohidfdlcjwdvi' AND t.tipp_tore_2>t.tipp_tore_1))); Nickname Vorname Nachname "phoackmu" "gcnaujuq" "meveclia" "xghphsay" "fpgqiwiu" "yqgqfpgw" "prymcdvh" "tlserwse" "ksiqjaph" "tobokvqc" "crdrdvhd" "rcroytks" "viapiltj" "jjxkvjxw" "gtxafmqo" "fyoahfdt" "umcndlkd" "wsdsbitp" "qixoenlt" "kcrjqbxi" "mitirecs" Gesamtlaufzeit der Abfrage: 32 ms. Benötigte Zeit zum Holen der Daten:16 ms. 7 Zeilen geholt. Durchschnittliche Punktezahl von Frauen und Männern SELECT b.geschlecht, avg(t.punkte) as punkteprotipp FROM benutzer b, tippt t WHERE b.nickname = t.nickname GROUP BY b.geschlecht ORDER BY punkteprotipp; Geschlecht Punkte pro Tipp "W" "1.9420849420849421" "M" "2.1244813278008299" Gesamtlaufzeit der Abfrage: 32 ms. Benötigte Zeit zum Holen der Daten:16 ms. 2 Zeilen geholt. Benutzer die nur auf spiele von gakyesqgyieaeyekqxhp getippt haben. SELECT * FROM benutzer b WHERE EXISTS (SELECT * FROM tippt t WHERE t.nickname = b.nickname) AND NOT EXISTS (SELECT * FROM tippt t1, spiel s1 WHERE b.nickname = t1.nickname AND t1.spielid = s1.spielid AND (s1.mannschaft_1 != 'gakyesqgyieaeyekqxhp' AND s1.mannschaft_2 ! ='gakyesqgyieaeyekqxhp')); Nickname Vorname Nachname Passwort Email "mcrvctig" "ugujyjfq" "bliaplcr" "whevlw" "ivpuieplvgercxjm "M" kaqokvjan" Geschlecht Tippgemeinschaft "" Gesamtlaufzeit der Abfrage: 15 ms. Benötigte Zeit zum Holen der Daten:0 ms. 1 Zeilen geholt. tippgemeinschaft mit der Anzahl ihrer noch offenen Bewerbungen SELECT t.name, count(*) as offene_bewerbungen FROM tippgemeinschaft t, bewirbt b WHERE b.gemeinschaft = t.name GROUP BY t.name ORDER BY offene_bewerbungen DESC; Gemeinschaft Offene Bewerbungen "iykhdhegfs" "10" "kyicgmovbu" "10" "oduiqhjmim" "9" "itxvkecliv" "9" "cekmrhyodh" "8" "lswcjavyln" "8" "ovuapcekhe" ..... Gesamtlaufzeit der Abfrage: 32 ms. Benötigte Zeit zum Holen der Daten:15 ms. 39 Zeilen geholt. "7" User, und deren Spiele, auf die sie noch nicht getippt haben SELECT b.nickname, s.spielid, s.mannschaft_1, s.mannschaft_2 FROM benutzer b, spiel s WHERE CURRENT_TIMESTAMP < s.begin AND NOT EXISTS (SELECT * FROM tippt t WHERE s.spielid = t.spielid AND b.nickname = t.nickname) ORDER BY b.nickname; nickname spielid mannschaft_1 mannschaft_2 "acdnkpsl" "82" "vfdpciefoyltfoftrlqq" "rbdtfaudydcnwwjcdoxk" "acdnkpsl" "15" "yfrnguyfbnnmvkslykkh" "gakyesqgyieaeyekqxhp" "acdnkpsl" "29" "rbdtfaudydcnwwjcdoxk" "uqcykiubqnkiremasvso" "acdnkpsl" "32" "pjphsokdseexcxuprgev" "edamjcirfjkjfrrdwdpl" "acdnkpsl" "40" "yieenijfypbkqcnivkks" "grokyikptxhuppyrgvqb" "acdnkpsl" "53" "bouitdbohidfdlcjwdvi" "yfrnguyfbnnmvkslykkh" "acdnkpsl" "72" "pgkswynbwveumvreyxgk" "utdjthhikojhrqcvwvml" "acdnkpsl" "55" "esmxtgpnyuhfrnjsehul" "ncnshnniplanbyfsoapt" ... Gesamtlaufzeit der Abfrage: 703 ms. Benötigte Zeit zum Holen der Daten:750 ms. 13057 Zeilen geholt. Spiele auf die kein Tipp abgegeben wurde SELECT * FROM spiel s WHERE NOT EXISTS ( SELECT * FROM tippt t WHERE s.spielid = t.spielid); Spielid Begin Stadion "56" "2006-06-21 16:00:00" "kqudfljbmelu "bhyajsqcdnj iibqcdlrpkmlp h bonxw" Infotext Spielart "9" "2006-06-21 16:00:00" "lgjmbsltama "knvvycxwrpf "Semifinale" bqxdnxqwed hu bxvrlmakf" Mannschaft_1 Mannschaft_2 Tore_1 "Achtelfinale" "yieenijfypbk qcnivkks" "utptchsexwi bvvhbavmb" Tore_2 "1" "0" "vrhdrxxgexo "cgnpvkatoks "1" cjlenmulx" nqululsbp" "2" Gesamtlaufzeit der Abfrage: 16 ms. Benötigte Zeit zum Holen der Daten:15 ms. 2 Zeilen geholt. Alle Spiele, auf die man nicht mehr tippen kann und, falls eingetragen, ihre Ergebnisse, sowie, falls vorhanden, der Tipp des Users 'acdnkpsl' für jedes Spiel. SELECT s.spielid, s.begin, s.mannschaft_1, s.mannschaft_2,s.spielart, s.stadion, s.tore_1, s.tore_2, t.tipp_tore_1, t.tipp_tore_2 ,t.punkte FROM spiel s LEFT OUTER JOIN (SELECT * FROM tippt where nickname='acdnkpsl')as t ON s.spielid = t.spielid WHERE s.begin< now() ORDER BY s.begin ; Spielid Begin Mannschaft 1 Mannschaft 2 Spielart Stadion Tore 2 Tipp Tore 1 Tipp Tore 2 Punkte "5" "2006-0601 17:00:00" "xfafetnlxjtp xllqompo" "fdrguvbdla swfddixcig" "Halbfinale" "ymxtxwkef "0" qeylvecskim kwmnagylk a" "0" "" "" "" "80" "2006-0601 17:00:00" "pjphsokdse "wsxftagalp excxuprgev bjhmowuhp " d" "Viertelfinal e" "ieejxljrpkfs "2" ssnxvoeshu gffbwlkp" "0" "2" "2" "4" "66" "2006-0601 17:00:00" "tfdocquvua chanhdplqq " "tmkjfoniue hvavcoaqto nasxmlwdxl " "1" "1" "" "" "" "59" "2006-0601 17:00:00" "gakyesqgyi "lfqudfkmoo "Viertelfinal eaeyekqxhp gbmwupdon e" " n" "xgergavkys "3" opjuvaennfk axvhcqvgx" "0" "" "" "" "58" "2006-0601 18:00:00" "boksyujnlu "lfqudfkmoo "Semifinale" "kqudfljbmel "0" cobpvhucys gbmwupdon uiibqcdlrpk " n" mlpbonxw" "2" "3" "3" "3" "qyuqdxoaw "Halbfinale" fbfnrxkswly" Tore 1 Gesamtlaufzeit der Abfrage: 31 ms. Benötigte Zeit zum Holen der Daten:32 ms. 33 Zeilen geholt. Datenmodifikations-Kommandos INSERT INTO spiel(begin,spielart,stadion,mannschaft_1,mannschaft_2) VALUES('2006-06-13 18:00:00','Vorrundengruppe','Gottlieb-DaimlerStadion','Frankreich','Schweiz'); Abfrage war erfolgreich durchgeführt: 1 Zeilen, 31 ms Ausführungszeit. UPDATE mannschaft SET infotext = 'Das ist die Nationalmannschaft der Bundesrepublik Deutschland' WHERE name = 'Deutschland'; Abfrage war erfolgreich durchgeführt: 1 Zeilen, 63 ms Ausführungszeit. Teil 6: Views Eine Sicht die die Topliste der Benutzer mit Punkten und der durchschnittlichen Punktezahl pro Tipp des Users repräsentiert. CREATE VIEW topliste AS SELECT t.nickname, sum(t.punkte) as punkte, avg(punkte) as durchschnitt FROM tippt t, benutzer b WHERE b.nickname = t.nickname GROUP BY t.nickname ORDER BY punkte DESC; Abfrage war erfolgreich nach 0 ms. Keine Zeilen geliefert. Eine Sicht die die Topliste der Tippgemeinschaften mit ihren Punkten repräsentiert. CREATE VIEW tippgemeinschaft_topliste AS SELECT t.name, sum(tp.punkte) as punkte FROM tippgemeinschaft t, benutzer b, tippt tp WHERE b.tippgemeinschaft = t.name AND b.nickname = tp.nickname GROUP BY t.name ORDER BY punkte DESC; Abfrage war erfolgreich nach 47 ms. Keine Zeilen geliefert. Eine Sicht die nur für normale Benutzer geeignet ist, damit man nicht die Passwörter sehen kann. CREATE VIEW benutzer_view AS SELECT b.nickname, b.vorname, b.nachname, b.geschlecht, b.email, b.tippgemeinschaft FROM benutzer b; Abfrage war erfolgreich nach 94 ms. Keine Zeilen geliefert. Teil 7: Webanbindung der Datenbank Siehe .war-Datei :) Teil 8: Indexierung CREATE INDEX benutzer_idx ON benutzer (tippgemeinschaft); CREATE INDEX bewirbt_idx ON bewirbt (gemeinschaft); CREATE INDEX mannschaft_idx ON mannschaft (vorrundengruppe); CREATE INDEX spiel_idx ON spiel (begin); Um die Zeitunterschiede zu erkennen, haben wir uns eine neue große Datenbank mit ca 50Mbyte Einträgen generiert. Datenbank ohne Indizes Datenbank mit Indizes Kommentar Gesamtlaufzeit der Abfrage: 2390 ms. Benötigte Zeit zum Holen der Daten:140 ms. 1000 Zeilen geholt. Gesamtlaufzeit der Abfrage: 641 ms. Benötigte Zeit zum Holen der Daten:78 ms. 1000 Zeilen geholt. Gesamtlaufzeit der Abfrage: 1188 ms. Benötigte Zeit zum Holen der Daten:0 ms. 12 Zeilen geholt. Gesamtlaufzeit der Wir gehen über keinen Abfrage: 1188 ms. Index. Benötigte Zeit zum Holen der Daten:0 ms. 12 Zeilen geholt. Gesamtlaufzeit der Abfrage: 23828 ms. Benötigte Zeit zum Holen der Daten:31 ms. 13 Zeilen geholt. Gesamtlaufzeit der Abfrage: 6547 ms. Benötigte Zeit zum Holen der Daten:15 ms. 13 Zeilen geholt. Gesamtlaufzeit der Abfrage: 422 ms. Benötigte Zeit zum Holen der Daten:0 ms. 2 Zeilen geholt. Gesamtlaufzeit der Wir gehen über keinen Abfrage: 422 ms. Index. Benötigte Zeit zum Holen der Daten:0 ms. 2 Zeilen geholt. Gesamtlaufzeit der Gesamtlaufzeit der Die 1. Abfrage Die 3. Abfrage Wir gehen über keinen Datenbank ohne Indizes Datenbank mit Indizes Kommentar Abfrage: 109 ms. Benötigte Zeit zum Holen der Daten:0 ms. 0 Zeilen geholt. Abfrage: 109 ms. Index. Benötigte Zeit zum Holen der Daten:0 ms. 0 Zeilen geholt. Gesamtlaufzeit der Abfrage: 422 ms. Benötigte Zeit zum Holen der Daten:47 ms. 500 Zeilen geholt. Gesamtlaufzeit der Abfrage: 125 ms. Benötigte Zeit zum Holen der Daten:63 ms. 500 Zeilen geholt. Die 6. Abfrage Gesamtlaufzeit der Abfrage: 1625 ms. Benötigte Zeit zum Holen der Daten:1047 ms. 19500 Zeilen geholt. Gesamtlaufzeit der Abfrage: 1406 ms. Benötigte Zeit zum Holen der Daten:1094 ms. 19500 Zeilen geholt. Hier verwenden wir wieder die etwas kleinere Datenbank, da er sonst wegen der Not Exists Anweisung ewig lange sucht. Die Abfrage nach dem Timestamp wurde dabei entfernt, da sonst nichts ausgegeben wird. Gesamtlaufzeit der Abfrage: 31 ms. Benötigte Zeit zum Holen der Daten:16 ms. 2 Zeilen geholt. Gesamtlaufzeit der Abfrage: 31 ms. Benötigte Zeit zum Holen der Daten:16 ms. 2 Zeilen geholt. Hier verwenden wir wieder die etwas kleinere Datenbank, da er sonst wegen der Not Exists Anweisung ewig lange sucht. Kein Geschwindigkeitsvorteil, da wir nicht über den Index gehen. Gesamtlaufzeit der Abfrage: 10265 ms. Benötigte Zeit zum Holen der Daten:5328 ms. 50000 Zeilen geholt. Gesamtlaufzeit der Abfrage: 8297 ms. Benötigte Zeit zum Holen der Daten:5109 ms. 50000 Zeilen geholt. Die 9. Abfrage Teil 9: Transaktionen a) Ausführen einer Transaktion Vor der Transaktion "Alex" "Alexander" "Waldmann" "qwerty" "" "M" "Die Gemeinschaft" "Andi1" "Andreas" "Müller" "andi" "" "M" "Die Gemeinschaft" Transaktion BEGIN; Delete from benutzer where nickname = 'Andi1'; COMMIT; Nach der Transaktion "Alex" "Alexander" "Waldmann" "qwerty" "" "M" "Die Gemeinschaft" b) Abbrechen einer Transaktion Vor der Transaktion "Emil01" "Emil" "Frei" "lkjh" "" "M" "" "Alex" "Alexander" "Waldmann" "qwerty" "" "M" "Die Gemeinschaft" "Andi1" "Andreas" "Müller" "andi" "" "M" "Die Gemeinschaft" "FLo_" "Florian" "Thiemer" "1234" "" "M" "FreieDeutscheJ ugend" "Juliuz" "Julius" "Dannert" "qwertz" "" "M" "FreieDeutscheJ ugend" "HansOtto" " David" "Iwanowitsch" "abcd" "" "M" "FreieDeutscheJ ugend" "Hans01" "Hans" "Kanns" "hansi" "" "M" "Gurkentruppe" Abfrage: BEGIN; DELETE FROM benutzer WHERE geschlecht = 'M'; ROLLBACK; Nach der Transaktion: "Emil01" "Emil" "Frei" "lkjh" "" "M" "" "Alex" "Alexander" "Waldmann" "qwerty" "" "M" "Die Gemeinschaft" "Andi1" "Andreas" "Müller" "andi" "" "M" "Die Gemeinschaft" "FLo_" "Florian" "Thiemer" "1234" "" "M" "FreieDeutscheJ ugend" "Juliuz" "Julius" "Dannert" "qwertz" "" "M" "FreieDeutscheJ ugend" "HansOtto" " David" "Iwanowitsch" "abcd" "" "M" "FreieDeutscheJ ugend" "Hans01" "Hans" "Kanns" "hansi" "" "M" "Gurkentruppe" Es ist also nichts passiert. Projektbericht Zu Beginn des Projektes haben wir uns zu dritt hingesetzt und gemeinsam das ERDiagramm entworfen. Zu Hause hat sich dann Julius hingesetzt und daraus ein erstes Relationales Schema entwickelt. Dies Wurde dann von David und Flo verbessert. Später wurden noch zwei Veränderungen vorgenommen. Die erste betraf allein die Namensgebung. Beim Programmieren hatte es sich als unpraktisch herausgestellt, das die Tabellen so lange Namen haben. So wurde z.B. Fußballmannschaft in Mannschaft umbenannt. Die zweite Änderung war das Einfügen einer fünften Entität: dem Stadion. Zur Koordination der Programmieraufgaben wurde bei Spline ein SplineForge Projekt angelegt. Dadurch stand uns ein SVN-Repository und eine Online-Task-Management-Tool zur Verfügung. In dieses Task-Management-Tool wurden zunächst alle Geschäftsprozess eingetragen. Am Anfang wurde das Task-Management-Tool auch genutzt, später jedoch nur vereinzelt. Die Aufgabenverteilung erfolgte dann meist mündlich. Das SVN-Repository war jedenfalls eine große Erleichterung, die wir auch schon im Software-Praktikum in den Semesterferien kennengelernt hatten. Das wir keinerlei Erfahrungen im Programmieren mit JSP Servlets und Co hatten, gestaltete sich gerade der Einstieg ins Programmieren schwierig. Je mehr wir programmierten um so wuchs auch unsere Erfahrung und zum Ende hin war das Implementieren der Geschäftsprozess nur noch eine Zeit-, keine Könnensfrage mehr. Unser Konzept sie so aus, dass man eine Java-Klasse (DBAction.java) hat in der sämtliche SQL anfragen gesammelt sind, die etwas zurückliefern. Zwecks Objektorientierung haben wir für alle Entitäten Objekt-Klassen geschrieben, die von den Methoden zurückgeliefert werden. So liefert die Funktion getUserByName(String nickname) ein User-Objekt zurück, das 'nickname' repräsentiert. Intern sehen die Funktionen der DBAction recht ähnlich aus. Sie bauen am Anfang mit Hilfe der Klasse DBConnection eine Verbindung zur Datenbank auf uns senden dann eine SQL-Anfrage. Dann kopieren sie die Daten in das passende Objekt, schließen die Verbindung und liefern das eben erstellte Objekt zurück. SQL-Anfragen, die nichts zurück liefern werden in der DBWrite.java gesammelt. Ein beliebter Fehler bei den SQL anfragen war: ResultSet rs = dbc.querry("SELECT nickname, vorname, nachname, geschlecht, tippgemeinschaft, email" + // Achtung der Fehler war schon. "FROM benutzer " + "WHERE nickname='"+nickname+"' "); Hier fehlt ein Leerzeichen hinter email. Wenn man dies vergisst ist die gesamte SQLAnfrage fehlerhaft. Bevor man etwas ins Repository eincheckte testet man deshalb kurz, ob es auch das tat, was es sollte. Der ultimative Test war jedoch das Benutzen des Tippspieles währen der WM. Zu diesem Zwecke richtete Julius sein Computer mit Hilfe eine DynDNS von www.dyndns.com als Webserver ein. Dieser funktionierte zwar nur sehr unzuverlässig, es reichte jedoch aus um mit 11 Freunden das Tippspiel zu testen. Dabei fanden wir einige Fehler, die vorher nicht aufgefallen waren, die sich aber auch leicht beheben ließen. Des weitern integrierten wir noch einige Funktionen, die von den Benutzern gewünscht wurden. So wird jetzt, wenn man sich eingeloggt immer rechts oben der aktuelle Punktestand angezeigt und auf der Startseite werden die nächsten, und die letzten drei Spiele angezeigt.