9.4 VERKNÜPFUNG VON TABELLEN

 

 

EINFÜHRUNG

 

Wie schon der Name sagt, ist das Relationale Datenbankmodell besonders gut geeignet, um Informationen aus verschiedenen Tabellen oder ganzen Datenbanken zu verknüpfen. Dies spielt in der Praxis eine ausserordentlich grosse Rolle, denn es lassen sich damit wichtige neue Informationen gewinnen, ganz im Sinn des Zitats von Aristoteles "Das Ganze ist mehr als die Summe seiner Teile" [mehr... Das Verknüpfen von Personen-Datenbanken aus ganz verschiedenen Bereichen
birgt aber auch Gefahren in sich, da sie zu Informationen führen, die in
den einzelnen Datenbanken harmlos sind, aber in ihrer Kombination hoch
brisant sein können und eventuell dem Datenschutzgesetz widersprechen.
].

 

 

VERWALTUNG EINES SPORTTAGES

 

Zur Demonstration für den Umgang mit mehreren Tabellen soll es deine Aufgabe sein, ein Programm für den Schulsporttag zu erstellen, um die sportlichen Leistungen von Personen in verschiedenen Disziplinen zu speichern und Ranglisten zu erstellen. Als Sportarten werden dabei eine Laufdisziplin und der Hoch- und Weitsprung betrachtet. Eine auf den ersten Blick plausible Lösung könnte darin bestehen, dass du alle Personendaten aus der Tabelle person extrahierst und in einer neuen, mit Leistungsdaten ergänzten Tabelle übernimmst. Dies ist deswegen ungünstig, weil  jede Mutation von Personen in zwei Tabellen oder Datenbanken vorzunehmen wäre [mehr... Bei der Planung einer Datenbank (Datenbankdesign) gibt es einige
Grundregeln zu beachten. Eine davon sagt aus, dass man gleiche
Informationen nicht über mehrere Tabellen verstreut speichern
sollte (Orthogonalität, Redundanzfreiheit)
].

Einfacher und sicherer ist es, eine zweite Tabelle mit dem Leistungsdaten zu erstellen, welche lediglich über die eindeutige Identifikationszahl personid mit der Personentabelle verknüpft ist. Daher erzeugst du die Tabelle sport mit dem INTEGER Feld personid, sowie den FLOAT Feldern für die Leistungen im Lauf,  Hoch- und Weitsprung.

from sqlite3 import *

with connect("schule.db") as con:
    cursor = con.cursor()
    sql = """CREATE TABLE sport
             (personid INTEGER, 
             lauf FLOAT, 
             hochsprung FLOAT, 
             weitsprung FLOAT)"""  
    cursor.execute(sql)       
print("Done")
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Löschen kannst du sie mit:

from sqlite3 import *

with connect("schule.db") as con:
    cursor = con.cursor()
    cursor.execute("DROP TABLE sport")    
print("Done")
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Zur komfortablen Datenverwaltung schreibst du einen benutzerfreundlichen GUI-basierten Sport-Manager. Für das Vorgehen orientierst du dich am vorher verwendeten Datenbank-Manager, denn die Grundprinzipien bleiben die gleichen. Den Programmcode kannst du von http://www.programmierkonzepte.ch/download/sportmanager.zip downloaden und dann in den TigerJython-Editor kopieren. Beim Start präsentiert sich der Sport-Manager wie folgt:

Zuerst sind alle Leistungsfelder leer und du kannst nun die Leistungsdaten aller Personen eingeben. Bei solchen, die eine Sportart nicht ausüben, belässt du das leere Eingabefeld.

Für das Navigieren verwendest du denselben Code wie im Datenbank-Manager.  Aus der Liste resultSet und dem currentIndex kannst du die personid der aktuellen Person wie folgt beziehen:

personid = resultSet[currentIndex][0]

Beim Klicken von Save werden die Leistungsdaten lValue, hValue, wValue mit dem SQL-Befehl

INSERT INTO sport VALUES (%s, %s, %s, %s)" %(ident, lValue, hValue, wValue)

in die Tabelle geschrieben. Ist der Datensatz für die betreffende Person schon vorhanden, so wird er vorher gelöscht.

 

 

AUSSCHREIBEN DER RESULTATE UNTER VERWENDUNG VON JOIN

 

Nachdem die Leistungsdaten erfasst worden sind, möchte man die Leistungen auf Grund bestimmter Vorgaben anzeigen oder ausdrucken. (Ein Datenauszug wird auch ein Report genannt.) Dazu musst du im SELECT-Befehl beide Tabellen mit JOIN verbinden und mit der Option ON angeben, welches die Übereinstimmungen sind. Um die Leistungen aller Personen zu erhalten, schreibst du also:

from sqlite3 import *
from prettytable import printTable

with connect("schule.db") as con:
    cursor = con.cursor()
    sql = """SELECT familienname, vorname, lauf, hochsprung, weitsprung 
             FROM person JOIN sport 
             ON person.personid == sport.personid""" 
    cursor.execute(sql)       
    printTable(cursor)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

und du erhältst etwa Folgendes:

Beim Drücken der Buttons Lauf, Hoch oder Weit werden die Resultate in einer Rangliste ausgegeben. Der SQL-Befehl für den Lauf lautet:

"""SELECT familienname, vorname, lauf 
   FROM person JOIN sport 
   ON person.personid == sport.personid 
   ORDER BY lauf ASC"""

und du siehst etwa folgende Ausgabe:

 

 

MEMO

 
Mit JOIN lassen sich mehrere Tabellen verknüpfen. In diesem einfachen Fall ist dies auch mit einem WHERE möglich.

from sqlite3 import *
from prettytable import printTable

with connect("schule.db") as con:
    cursor = con.cursor()
    sql = """SELECT familienname, vorname, lauf, hochsprung, weitsprung 
             FROM person, sport
             WHERE person.personid == sport.personid""" 
    cursor.execute(sql)       
    printTable(cursor)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

 

 

AUFGABEN

 

1.


Löscht man eine Person aus der Tabelle person, so sollten auch ihre Leistungsdaten gelöscht werden, da es sonst innere Widersprüche (Inkonsitenzen) in der Datenbank hat. Ergänze den Datenbank-Manager entsprechend, damit die Datenintegrität in jedem Fall erhalten bleibt.


2.


Gib Leistungsdaten deiner ganzen Schulklasse ein.


3*.


Führe eine Punktbewertung nach folgender Punkteverteilung ein und ermittle die Reihenfolge der Personen gemäss der Gesamtpunkzahl.

Lauf
Laufzeit
> 16
> 15
> 14
> 13
<= 13
Punkte
0
1
2
3
4


Hochsprung
Höhe
< 1.00
< 1.10
< 1.20
< 1.30
>= 1.30
Punkte
0
1
2
3
4


Weitsprung
Weite
< 3.00
< 3.50
< 4.00
< 4.50
>= 4.50
Punkte
0
1
2
3
4

Anleitung: Erzeuge die Tabelle score mit dem SQL-Befehl:

CREATE TABLE score
          (personid INTEGER, 
           lauf INTEGER, 
           hochsprung INTEGER, 
           weitsprung INTEGER,
           total INTEGER)

welche die Felder für die Personen-Id und  Punktzahlen der einzelnen Disziplinen sowie die Gesamtpunktzahl  enthält. Füge in den Sport-Manager einen zusätzlichen Button "Gesamt" ein. Beim Drücken werden zuerst alle Einträge in score gelöscht und ausgehend von den Werten in der Tabelle sport neu eingetragen. Nachher werden die Datensätze nach der Totalpunktzahl sortiert ausgeschrieben.