PMG1719/DB Beleg/Max
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>SQL</language> == Themenwahl und Ziel des Beleges == In meinem Datenbankbeleg möchte ich die Umsetzung eines Rollenspiel-Videospieles realisieren. Dieses Thema wählte ich, da ich mich freizeitlich oft an der Entwicklung interaktive Inhalte, wie zum Beispiel Videospiele, versuche. Das Entwerfen eines geeigneten Datenbanksystems zu dieser Thematik schätzte ich somit als herausforderndes, aber ebenso anschauliches Exempel für die Anforderungen an den Beleg an. == Gameplay == Zum Verständnis weiterer Inhaltsaspekte des Beleges ist ein Verständnis über die verwendeten Strukturen, welche auf dem Spielfluss des Rollenspieles (dem so genannten Gameplay) basieren, notwendig. Daher werden diese im Folgenden kurz erläutert, um eventuelle Missverständnisse oder sogar Unverständlichkeiten im ERM zu vermeiden. * SPIELER - Das zentrale Objekt > Vom SPIELER gehen die zentralen Beziehungen aus. Für jeden Spieler wird eine neue, eindeutige '''Player_ID''' verwendet. Um im Spiel unter einem Synonym in Erscheinung treten zu können, wird ein Username benutzt. Ein '''Level''' zeigt, wie fortgeschritten ein Spieler ist. Für einen Levelaufstieg ist die '''Erfahrung''' ausschlaggebend. Wird eine bestimmte Erfahrungsgrenze überschritten, so steigt der Spieler ein Level auf. Wie hoch diese Erfahrungsgrenze ist, wird über einen weiteren Mechanismus (welcher im Modell selbstverständlich nicht implementiert ist) errechnet. Dieser sollte ermöglichen, dass SPIELER eines höheren Levels mehr Erfahrung zum Levelaufstieg benötigen. Umzusetzen wäre diese Technik beispielsweise über einen logarithmischen Zusammenhang. Die '''Lebenspunkte''' zeigen, wie viel Schaden ein Spieler erleiden kann, bevor er im Spiel stirbt. * MONSTER > MONSTER geben Spielern die Möglichkeit im Spiel weitere '''Erfahrung''' zu erhalten. Jedes MONSTER besitzt dabei eine eindeutige '''ID''' sowie einen '''Namen''', welcher im Spiel angezeigt werden könnte, sobald sich ein Spieler nähert. * CLAN > Clans sollen Spielern die Möglichkeit geben, Bündnisse, in welchen sie gemeinsam in Erscheinung treten können, zu erstellen. Jeder Spieler kann dabei in genau einem Clan sein, natürlich kann es auch Spieler ohne festen Clan geben, somit kann man den aktuellen Clan auch jederzeit verlassen. Neben einer eindeutigen '''ID''' besitzt jeder Clan einen ''Namen'' und einen '''Anführer''', welcher durch die jeweilige ID des Spielers festgelegt wird. Dieser kann als spezielle Einstellung im Clan eine '''Levelgrenze''' festlegen, welche bestimmt, welches Minimumlevel Spieler besitzen müssen, welche dem Clan beitreten wollen. Somit kann ausgeschlossen werden, dass neue Spieler mit einem niedrigen Level den Clan belästigen. Die Kapazität des Clans gibt an, wie viele Mitglieder er maximal aufnehmen kann. == Modellierung der Datenbank == Entity Relationship Model (ERM) [[Bild:Maxschloool_ERM_Screen.JPG]] - Konkretes Relationship Model (RM) [[Bild:Maxschloool_RM_Screen.JPG]] == Grundlegende Begriffe mit Bezug zum Modell == Die im Modell angewandten Techniken sind auf Grundkenntnisse der Datenbankmodellierung zurückzuführen. Durch die nun folgende Wiederholung einiger Bestandteile versuche ich darüberhinaus zu begründen, wieso, bzw. wie ich die Umsetzung auf diesem Weg vollzogen habe. Die einzelnen Entitäten werden zur Übersichtlichkeit deshalb im Folgenden (wie im ERM) in Großbuchstaben (Capslog) dargestellt. '''1) Normalformen''' > Bei der Modellierung des Modelles liegt ein besonderer Wert auf der Einhaltung der ersten drei Normalformen, da diese Voraussetzung für ein gezielteres und einfacheres Arbeiten mit den Datensätzen begünstigen. * Erste Normalform > Alle Attribute der einzelnen Entitäten liegen atomar vor, sie sind somit nicht auf weitere Grundbestandteile aufzuspalten. * Zweite Normalform > Alle Nichtschlüsselattribute sind nur von einem Primärschlüssel abhängig, in meinem Modell von den jeweiligen IDs. * Dritte Normalform > Keine Nichtschlüsselattribute stehen in direkter Verbindung mit weiteren Nichtschlüsselattributen, ohne selbst als Primärschlüssel aufgespalten zu sein. Die Abhängigkeit zur jeweiligen ID ist eindeutig. '''2) Entitäten''' > Die zwischen den Entitäten vorherrschenden Beziehungen geben Aufschluss über die gegenseitigen Strukturen, welche sich primär durch logische Konsequenzen aus dem Spielfluss (dem Gameplay) des Rollenspiels ergeben. Zur speziellen Erläuterung dafür dient der vorhergehende Inhaltsabschnitt "Gameplay". * 1:1-Beziehung > Diese Kardinalität, welche lediglich zwischen SPIELER und MONSTER herrscht, ermöglicht eine jeweils eineindeutige Zuordnung. Diese habe ich in diesem Fall gewählt, da jeweils ein SPIELER genau ein MONSTER besiegen kann, bzw. zu einem Zeitpunkt ein MONSTER von nur genau einem SPIELER getötet werden kann. * 1:n-Beziehung > Für die meisten Relationen erwies sich diese Kardinalität für am sinnvollsten. Dies lässt sich unter der Maßgabe der im Voraus erklärten Gameplay-Strukturen besonders damit begründen, dass jeder SPIELER als zentrales Objekt lediglich die Möglichkeit der Nutzung genau eines PERKs, bzw. dem Beitritt in nur einem CLAN besitzt. Zwischen PERK, bzw. ITEM und EFFEKT wird diese Kardinalität verwendet, da beide Entitäten jeweils nur einen Spezialeffekt nutzen sollen. Die Umsetzung dieser Kardinalität wird durch die Verwendung eines Fremdschlüssels erreicht. Diese wird bei mir besonders im RM erkennbar, da eine Visualisierung im ERM nicht möglich war. Die jeweilige Kennzeichnung der betreffendes IDs wird auch bei der Erstellung der Tabellen vorgenommen (FOREIGN KEYs). * n:m-Beziehung > Eine n:m-Kardinalität fand in meinem Modell lediglich bei der Relation zwischen SPIELERn und ITEMs Verwendung. Da viele (verschiedene) SPIELER im Besitz von mehreren ITEMs sein können, ist diese mehrdeutige Entitätszuordnung sinnvoll. Umgesetzt wurde sie (wie im RM erkennbar) durch eine Relationstabelle, in welcher SPIELER-ID und ITEM_ID als Fremdschlüssel in verbindung gesetzt wurden. == Erstellung der Tabellen == <code id="5c41785ade45a"> DROP TABLE IF EXISTS SPIELER; CREATE TABLE SPIELER( Player_ID int AUTO_INCREMENT, Username varchar(20), Level int, Erfahrung int, Lebenspunkte int, Coins int, Clan_ID int, Perk_ID int, PRIMARY KEY (Player_ID) ); DROP TABLE IF EXISTS CLAN; CREATE TABLE CLAN( Clan_ID int AUTO_INCREMENT, Name varchar(20), Kapazitaet int, Levelgrenze int, Anfuehrer_ID int, PRIMARY KEY (Clan_ID) ); DROP TABLE IF EXISTS MONSTER; CREATE TABLE MONSTER( Monster_ID int AUTO_INCREMENT, Name varchar(20), Erfahrung int, PRIMARY KEY (Monster_ID) ); DROP TABLE IF EXISTS PERK; CREATE TABLE PERK( Perk_ID int AUTO_INCREMENT, Name varchar(20), Beschreibung varchar(128), Effekt_ID int, PRIMARY KEY (Perk_ID) ); DROP TABLE IF EXISTS ITEM; CREATE TABLE ITEM( Item_ID int AUTO_INCREMENT, Name varchar(20), Beschreibung varchar(128), Effekt_ID int, PRIMARY KEY (Item_ID) ); DROP TABLE IF EXISTS EFFEKT; CREATE TABLE EFFEKT( Effekt_ID int AUTO_INCREMENT, Name varchar(20), Beschreibung varchar(128), PRIMARY KEY (Effekt_ID) ); DROP TABLE IF EXISTS besitzt; CREATE TABLE besitzt( Player_ID int, Item_ID int ); </code> == Befüllen der Datensätze == <code id="5c417a2f3b656"> INSERT INTO SPIELER VALUES(1, 'Schloool', 100, 250, 10, 10000, 1, 2); INSERT INTO SPIELER VALUES(2, 'ReitzOnTour', 23, 140, 10, 7346, 1, 1); INSERT INTO SPIELER VALUES(3, 'Helmbrecher2001', 12, 0, 10, 50, NULL, NULL); INSERT INTO SPIELER VALUES(4, 'BaytuzLP', 352, 254, 10, 152, 2, 1); INSERT INTO SPIELER VALUES(5, 'AlbanerAlban', 13, 12, 10, 200, 3, 1); INSERT INTO SPIELER VALUES(6, 'KokosPalme', 53, 234, 10, 1636, 3, 3); INSERT INTO SPIELER VALUES(7, 'KillerSchulsprecher', 12, 250, 10, 10000, NULL, 1); INSERT INTO SPIELER VALUES(8, 'Teichrose', 454, 250, 10, 16354524, 2, 4); INSERT INTO SPIELER VALUES(9, 'FeuerFeuerFEEEEUER', 23, 52, 10, 434, 1, 1); INSERT INTO SPIELER VALUES(10, 'JeckerJeschke', 47, 245, 10, 3433, 1, 3); INSERT INTO SPIELER VALUES(11, 'NiedererSchuster', 32, 250, 10, 3672, 3, 2); INSERT INTO SPIELER VALUES(12, 'Bobicar', 1, 0, 10, 0, NULL, NULL); INSERT INTO SPIELER VALUES(13, 'Metal4Life', 100, 24, 10, 10000, 2, NULL); INSERT INTO SPIELER VALUES(14, 'MakeGodsWordHappen', 140, 56, 10, 13060, 3, 4); INSERT INTO CLAN VALUES(1, 'Schlossergilde', 10, 75, 1); INSERT INTO CLAN VALUES(2, 'Hardcorezockerbande', 25, 75, 8); INSERT INTO CLAN VALUES(3, 'Die Heidenverfolger', 20, 20, 14); INSERT INTO MONSTER VALUES(1, 'Kanalratte', 10); INSERT INTO MONSTER VALUES(2, 'Giftmettigel', 20); INSERT INTO MONSTER VALUES(3, 'Gurkenfressender Eber', 50); INSERT INTO MONSTER VALUES(4, 'Schweinebärmann', 100); INSERT INTO MONSTER VALUES(5, 'Nacktmull mit Pollunder', 100); INSERT INTO MONSTER VALUES(6, 'Kruseltier', 125); INSERT INTO PERK VALUES(1, 'Schnelläufer', 'Lauf schneller als Usain Bolt!', 1); INSERT INTO PERK VALUES(2, 'Hochspringer', 'Spring höher als ein afrikanischer Springfloh!', 2); INSERT INTO PERK VALUES(3, 'Angreifer', 'Füge mehr Schaden als jemals zuvor zu!', 3); INSERT INTO PERK VALUES(4, 'Verteidiger', 'Erhöhe deine Verteidigung signifikant!', 4); INSERT INTO ITEM VALUES(1, 'Heiltrank', 'Heilt 5 Lebenspunkte', 5); INSERT INTO ITEM VALUES(2, 'Laufschuhe', 'Deine Beine laufen wie von alleine', 1); INSERT INTO ITEM VALUES(3, 'Fettes Stahlschild', 'Wehrt Angriffe besser ab', 4); INSERT INTO ITEM VALUES(4, 'Schwert des Unterganges', 'Zerstört jeden kläglichen Gegner', 3); INSERT INTO ITEM VALUES(5, 'Flügel des Icarus', 'Du lernst das Fliegen', 6); INSERT INTO ITEM VALUES(6, 'Göffel', 'Küchenutensil mit spitzen Zinken', 3); INSERT INTO EFFEKT VALUES(1, 'Geschwindigkeit', 'Erhöht Laufgeschwindigkeit'); INSERT INTO EFFEKT VALUES(2, 'Sprung', 'Erhöht Sprunghöhe'); INSERT INTO EFFEKT VALUES(3, 'Angriff', 'Erhöht Angriff'); INSERT INTO EFFEKT VALUES(4, 'Verteidigung', 'Erhöht Verteidigung'); INSERT INTO EFFEKT VALUES(5, 'Heilung', 'Erhöht Lebenspunkte'); INSERT INTO EFFEKT VALUES(6, 'Flug', 'Erlernt das Fliegen'); INSERT INTO besitzt VALUES(1, 2); INSERT INTO besitzt VALUES(1, 3); INSERT INTO besitzt VALUES(2, 5); INSERT INTO besitzt VALUES(4, 1); INSERT INTO besitzt VALUES(4, 2); INSERT INTO besitzt VALUES(4, 4); INSERT INTO besitzt VALUES(7, 3); INSERT INTO besitzt VALUES(9, 2); INSERT INTO besitzt VALUES(9, 3); INSERT INTO besitzt VALUES(11, 2); INSERT INTO besitzt VALUES(11, 5); INSERT INTO besitzt VALUES(13, 1); INSERT INTO besitzt VALUES(14, 2); INSERT INTO besitzt VALUES(14, 4); INSERT INTO besitzt VALUES(14, 6); </code> == Abfragen == '''Die dargebotenen Abfragen greifen alle auf die von mir entwickelte Datenbank zurück und sind in aufsteigender Komplexität angeordnet.''' Vielleicht kann die eine oder andere Abfrage als Übungsstoff für Schüler dienen, die "Musterlösung" kann durch einen Klick auf das Kreuz in der linken oberen Ecke der Runbox jederzeit wiederhergestellt werden. Über die zusätzliche Box könnt ihr selbst kreativ werden und weitere (für ein Videospiel dieser Art) relevante Abfragen erstellen. '''1) Welche Spieler sind im Spiel angemeldet?''' <run id="5c4176f7cb145">SELECT * FROM SPIELER;</run> '''2) Welche Monster gelten als bedrohlich, dh. lassen beim Tod mehr als 75 Erfahrungspunkte fallen?''' <run id="5c460fadf1e6a"> SELECT * FROM MONSTER WHERE Erfahrung > 75;</run> '''3) Was sind die 5 besten Spieler, dh. besitzen das höchste Level?''' <run id="5c45fbe335bf2"> SELECT Username, Level LIMIT 5 FROM SPIELER ORDER BY Level DESC LIMIT 5; </run> '''4) Welche Clans (mit Namen und Kapazität) gibt es, und was sind ihre jeweiligen Anführer?''' <run id="5c45fbe335c6b"> SELECT CLAN.Name, CLAN.Kapazitaet, SPIELER.Username AS Anführer FROM CLAN, SPIELER WHERE SPIELER.Player_ID = CLAN.Anfuehrer_ID;</run> '''5) Welche Items besitzt der Spieler mit der ID 14?''' <run id="5c4188a7afb0a"> SELECT ITEM.Name FROM SPIELER, ITEM, besitzt WHERE ITEM.Item_ID = besitzt.Item_ID AND besitzt.Player_ID = 14 AND SPIELER.Player_ID = 14; </run> '''6) Welche Eigenschaften (Name, Beschreibung, Effekt-ID) besitzen alle Perks und Items, die den Effekt "Angriff" nutzen?''' Achtung: Die in der Musterlösung verwendete "UNION"-Anweisung komprimiert die Informationen verschiedener Tabellen in einer einzigen Spalte. In einer alternativen Lösung könnten diese Informationen zB. in lediglich einer Zeile angezeigt werden. <run id="5c460fadf1efe"> SELECT PERK.Name AS Name, PERK.Beschreibung AS Beschreibung, PERK.Perk_ID AS ID FROM PERK, EFFEKT WHERE EFFEKT.Name = 'Angriff' AND PERK.Effekt_ID = EFFEKT.Effekt_ID UNION SELECT ITEM.Name, ITEM.Beschreibung, ITEM.Item_ID FROM ITEM, EFFEKT WHERE EFFEKT.Name = 'Angriff' AND ITEM.Effekt_ID = EFFEKT.Effekt_ID; </run> '''Box für freies Herumspielen am wahnsinnigen System''' <run id="5c45f927503db"></run> == Reflexion der Datenbank == == Changelog == '''11.01.19''' Konzeptidee, Skizzierung der ERM und RM in Dia, Anlegung der Tabellen im Wiki^ '''18.01.19''' Einfügen aller Grafiken, Einfüllen der Datensätze, Anlegung erster Abfragen und der Themenwahl, sowie nervenaufreibendes Fixen auftretender Fehler