SQLite Crash-Kurs für Android-Entwickler

Android-Anwendungen können Anwendungsdaten in SQLite-Datenbanken speichern. In diesem Lernprogramm erfahren Sie, wie SQLite-Datenbanken entworfen und bearbeitet werden.

Hier beginnen wir mit dem Entwurf und der Verwendung einer einfachen SQLite-Datenbank zur Verwaltung der Schachturnierergebnisse. Dieses Lernprogramm dient als kurzer Überblick über die Funktionsweise von SQLite-Datenbanken. Dieses Wissen wird dann in zukünftigen Entwicklungslehrgängen zur Implementierung datenbankgesteuerter Android-Anwendungen verwendet.

Fertig machen

Android-Anwendungen können eigene private SQLite-Datenbanken erstellen und bearbeiten. Entwickler können auch Datenbanken auf einem bestimmten Android-Emulator oder -gerät mit dem Befehlszeilentool sqlite3 des Android-SDK-Tools Android Debug Bridge (adb) prüfen und ändern..

In diesem Lernprogramm wird davon ausgegangen, dass Sie theoretisch über ein gewisses Verständnis relationaler Datenbanken verfügen, jedoch einige Auffrischungskurse benötigen, bevor Sie diese in Ihren Android-Anwendungen verwenden. Für dieses Lernprogramm sind keine Werkzeuge erforderlich. Es ist eher eine theoretische Übung.

Wenn Sie jedoch die Entwicklung von Android-Anwendungen planen, die auf SQLite-Datenbanken basieren, müssen Sie die für die Android-Entwicklung erforderlichen Tools wie das Android SDK und die Eclipse-IDE installieren. In Mobiletuts + finden Sie eine Vielzahl weiterer hilfreicher Android-Tutorials, die Ihnen bei der Durchführung dieser Aufgaben helfen.

Was ist SQLite??

SQLite ist eine kompakte relationale Datenbank-Engine. SQLite ist schnell und hat eine kleine Grundfläche, was es ideal für Android-Geräte macht. Anstelle der schwergewichtigen serverbasierten Datenbanken wie Oracle und Microsoft SQL Server wird jede SQLite-Datenbank in einer einzigen Datei auf der Festplatte gespeichert. Android-Anwendungen können private Anwendungsdaten in einer SQLite-Datenbank speichern.

Hinweis: Wenn Sie mit SQL vertraut sind, ist SQLite sehr einfach zu finden. SQLite ist im Grunde eine abgespeckte SQL-Datenbank-Engine für eingebettete Geräte. Spezifische Informationen zu SQLite und seinen Funktionen, Funktionen und Einschränkungen finden Sie in der Online-Dokumentation von SQLite.

Ein kurzer Überblick über die Datenbankgrundlagen

Eine Datenbank ist einfach eine strukturierte Art, Daten dauerhaft zu speichern. Daten werden in Tabellen gespeichert. Eine Tabelle enthält Spalten mit unterschiedlichen Datentypen. Jede Zeile in einer Tabelle steht für einen Datensatz. Es kann hilfreich sein, sich eine Tabelle wie eine Excel-Tabelle vorzustellen. Bei einer objektorientierten Programmierperspektive repräsentiert jede Tabelle in einer Datenbank häufig ein Objekt (dargestellt durch eine Klasse). Jede Tabellenspalte repräsentiert ein Klassenattribut. Jeder Datensatz in einer Tabelle repräsentiert eine bestimmte Instanz dieses Objekts.

Schauen wir uns ein kurzes Beispiel an. Nehmen wir an, Sie haben eine Unternehmensdatenbank mit einer Tabelle namens Employee. Die Employee-Tabelle kann fünf typisierte Spalten enthalten: EmployeeID (Nummer), Vorname (Zeichenfolge), Nachname (Zeichenfolge), Titel (Zeichenfolge) und Gehalt (Nummer). Sie können der Datenbank dann einen Datensatz für einen Mitarbeiter namens John Doe und einen separaten Datensatz für einen Mitarbeiter namens Anne Droid hinzufügen.

Daten innerhalb einer Datenbank sollen untersucht und manipuliert werden. Daten innerhalb einer Tabelle können sein:

  • Hinzugefügt (mit der EINFÜGEN Befehl)
  • Geändert (mit der AKTUALISIEREN Befehl)
  • Entfernt (mit der LÖSCHEN Befehl)

Sie können mithilfe einer so genannten Abfrage nach bestimmten Daten in einer Datenbank suchen. Eine Abfrage (mit dem SELECT-Befehl) kann eine oder mehrere Tabellen umfassen. Um eine Abfrage zu erstellen, müssen Sie die gewünschten Tabellen, Datenspalten und Datenwerte mithilfe der SQL-Befehlssprache angeben. Jeder SQL-Befehl wird mit einem Semikolon (;) beendet..

Die Schachturnier-Datenbank

Um wirklich zu verstehen, wie SQLite-Datenbanken funktionieren, können Sie ein einfaches Beispiel verwenden. Stellen wir uns vor, dass wir eine Anwendung haben, die die Punktzahlen der Spieler eines Gelegenheits-Schachturniers verfolgt. Die Punktzahlen des Spielers werden aufgezeichnet und am Ende einer Reihe von Spielen wird der Gewinner ermittelt. Das Gesamtturnierergebnis jedes Spielers wird anhand seiner Leistung am berechnet:

  • Vier Warmläufe (Gewicht: jeweils 10% der Gesamtpunktzahl)
  • Ein Halbfinale (Gewicht: 25% der Gesamtpunktzahl)
  • Ein Finale (Gewicht: 35% der Gesamtpunktzahl)

Hinweis: Für das Turnier können sich Spielerergebnisse auf eine Formel stützen, die die Zeit bis zum Gewinn des Spiels sowie die Art und Anzahl der verbleibenden Spielsteine ​​am Ende des Spiels berücksichtigt. Auf diese Weise erhält ein starker Spieler eine hohe Punktzahl, wenn er wenige mächtige Figuren verliert und das Spiel schnell gewinnt. Vielleicht werden Stil und Haltung von den Richtern berücksichtigt, um Spaß und leichtes Spiel zu fördern. Wie die Ergebnisse berechnet werden, ist für die Definition unserer Datenbank wirklich nicht wichtig. wir speichern sie einfach in der Datenbank. Der Einfachheit halber gehen wir davon aus, dass die Bewertungen auf einer Skala von 0-100 basieren.

Entwerfen des Datenbankschemas

Ein Datenbankschema ist einfach die Definition der Struktur der Datenbank in Form von Tabellen, Datenspalten und dergleichen. Das Schema für unsere Turnierdatenbank ist ziemlich einfach:

Das TournamentScores-Datenbankschema verfügt über drei Tabellen:

  • Die Players-Tabelle enthält Spielerinformationen.
  • Die Spieletabelle enthält Informationen zu jedem Spiel und wie viel es zum Gesamtturnierwert des Spielers zählt.
  • Die GameResults-Tabelle enthält die Spielergebnisse aller Spieler.

SQLite3 unterstützt die folgenden allgemeinen Datentypen für Spalten:

  • GANZE ZAHL (signierte ganze Zahlen)
  • ECHT (Gleitkommawerte)
  • TEXT (UTF-8 oder UTF-16-String; kodiert mit Datenbankcodierung)
  • KLECKS (Datenstück)

Wenn Sie festgelegt haben, welche Spalten für jede Tabelle erforderlich sind, können Sie einige Tabellen in Ihrem Datenbankschema erstellen.

Mit Tabellen arbeiten

Beginnen wir mit der Erstellung der Players-Tabelle. Diese Tabelle erfordert eine eindeutige Spieler-ID, um jeden Spieler zu referenzieren. Wir können dies zum Primärschlüssel machen (um einen Datensatz in dieser Tabelle eindeutig zu identifizieren) und das Attribut für die automatische Zuordnung festlegen. Autoincrement bedeutet, dass jedes Mal, wenn ein neuer Spieler-Datensatz hinzugefügt wird, der Datensatz eine neue, eindeutige Spieler-ID erhält. Wir möchten auch den Vor- und Nachnamen jedes Spielers speichern, wobei keine Nullen zulässig sind.
Hier können wir die CREATE TABLE-SQL-Anweisung verwenden, um die Players-Tabelle zu generieren:

CREATE TABLE-Spieler (ID INTEGER PRIMARY KEY-AUTOINCREMENT, fname TEXT NOT NULL, lname TEXT NOT NULL); 

Der Spieletisch ist sehr ähnlich. Wir benötigen eine eindeutige Spiel-ID, um jedes Spiel zu referenzieren. Wir möchten auch einen befreundeten Namen für jedes Spiel und einen Gewichtungswert dafür, wie viel das Spiel zum Endergebnis des Spielers zählt (in Prozent). Hier ist die SQL-Anweisung zum Erstellen der Games-Tabelle:

CREATE TABLE Spiele (ID INTEGER PRIMARY KEY AUTOINCREMENT, Spielername TEXT, Gewicht REAL DEFAULT .10 CHECK (Gewicht<=1)); 

Sie können Tabellen auch mit der Anweisung DROP TABLE löschen. Um beispielsweise die Games-Tabelle zu löschen, verwenden Sie den folgenden SQL-Befehl:

DROP TABLE Spiele; 

Tabellen mit Datensätzen füllen

Bevor wir fortfahren, fügen wir diesen Tabellen einige Daten hinzu. Um einen Datensatz zur Players-Tabelle hinzuzufügen, müssen Sie die Spaltennamen und die Werte in der angegebenen Reihenfolge angeben. Die folgende SQL-Anweisung verwendet beispielsweise den Befehl INSERT, um einen Datensatz für den Schachspieler Bobby Fisher hinzuzufügen:

INSERT in Players (fname, lname) WERTE ('Bobby', 'Fisher'); 

Wenn wir gerade dabei sind, werden wir zwei weitere Spieler hinzufügen: Bart Simpson (ein sehr erbärmlicher Schachspieler) und Garry Kasparov (vielleicht der beste Schachspieler aller Zeiten). Gleichzeitig müssen wir dem Spieltisch eine Reihe von Datensätzen hinzufügen. Zuerst fügen wir das Halbfinale hinzu, das 25 Prozent des Turniers des Spielers ausmacht:

EINFÜGEN in Spiele (Spielername, Gewicht) WERTE ('Halbfinale', 0,25); 

Dann fügen wir ein paar Warmläufe hinzu, die das Standardgewicht von 10 Prozent verwenden:

INSERT in Games (gamename) VALUES ('Warm-up Heat 1'); 

Schließlich fügen wir ein Finale von 35 Prozent des Gesamtturniers hinzu:

EINFÜGEN in Spiele (Spielername, Gewicht) WERTE ('Finale', .35); 

Abfragen von Tabellen nach Ergebnissen mit SELECT

Woher wissen wir, dass die hinzugefügten Daten in der Tabelle enthalten sind? Das ist einfach. Wir fragen einfach alle Zeilen in einer Tabelle mit einer SELECT-Anweisung ab:

SELECT * FROM Spiele; 

Dies gibt alle Datensätze in der Spieletabelle zurück:

id gamename weight ----- --------------- ------ 1 Halbfinale 0,25 2 Aufwärmen 1 0,1 3 Aufwärmen 2 0,1 4 Warm Aufwärmen 3 0,1 5 Aufwärmen 4 0,1 6 Schluß 0,35 

Verwenden von Spaltenaliasen und berechneten Spalten

Wir können auch eigene Spalten erstellen und diese Aliasnamen geben. Wir können zum Beispiel einen Spaltenalias namens PlayerName erstellen, der eine berechnete Spalte ist: Der Vor- und Nachname des Spielers wird mit || verkettet Operator, getrennt durch ein Leerzeichen:

SELECT fname || "|| lname AS PlayerName, ID FROM Players; 

Diese Abfrage liefert die folgenden Ergebnisse:

Spielername id ------------ - Bobby Fisher 1 Bart Simpsen 2 Garry Kasparov 3 

Daten in Tabellen ändern

Der Nachname von Bart (Spieler-ID 2) ist falsch geschrieben. Um die Players-Tabelle mit der korrekten Schreibweise zu aktualisieren, können Sie den Befehl UPDATE verwenden:

UPDATE-Spieler SET lname = "Simpson" WHERE playerid = 2; 

Sie können Zeilen mit der DELETE-Funktion aus einer Tabelle löschen. So löschen Sie beispielsweise den gerade aktualisierten Datensatz:

DELETE FROM Players WHERE SpielerID = 2; 

Sie können alle Zeilen in einer Tabelle löschen, indem Sie die WHERE-Klausel nicht angeben:

DELETE FROM Players; 

Verwenden von Fremdschlüsseln und zusammengesetzten Schlüsseln

Nachdem wir nun unsere Spieler und Spiele eingerichtet haben, erstellen wir die Tabelle "GameResults". Dies ist eine kompliziertere Tabelle. Die GameResults-Tabelle kombiniert Spieler-IDs aus der Players-Tabelle mit den Game-IDs aus der Spieletabelle und listet dann die Punkte auf, die der Spieler für das bestimmte Spiel verdient hat. Spalten, die auf diese Weise mit anderen Tabellen verknüpft sind, werden häufig als Fremdschlüssel bezeichnet. Wir möchten einzigartige Spieler-Spiel-Kombinationen, also erstellen wir einen zusammengesetzten Primärschlüssel aus den Fremdschlüsseln des Spielers und des Spiels, um einen GameResults-Datensatz eindeutig zu identifizieren. Schließlich erzwingen wir, dass die Ergebnisse ganze Zahlen zwischen 0 und 100 sind.

CREATE TABLE GameErgebnisse (playerid INTEGER-REFERENZEN Spieler (id), gameid INTEGER-REFERENZEN Spiele (id), Punktzahl INTEGER CHECK (score)<=100 AND score>= 0), PRIMARY KEY (playerid, gameid)); 

(Hinweis: SQLite erzwingt keine Fremdschlüsseleinschränkungen, Sie können sie jedoch trotzdem einrichten und die Einschränkungen durch Erstellen von Triggern erzwingen.)
Nun ist es Zeit, Daten in die GameResults-Tabelle einzufügen. Angenommen, Bobby Fisher (Spieler-ID 1) hat im Halbfinale (Spiel-ID 1) 82 Punkte erzielt. Sie können den folgenden SQL-Befehl verwenden, um den entsprechenden Datensatz in die GameResults-Tabelle einzufügen:

INSERT in GameResults (Spieler-ID, Spiel-ID, Score) VALUES (1,1,82); 

Nehmen wir nun an, das Turnier wird gespielt und die Ergebnisse werden der Tabelle "GameResults" hinzugefügt. Bobby ist ein guter Spieler, Bart ist ein schrecklicher Spieler und Garry spielt immer ein perfektes Spiel. Nachdem die Datensätze der GameResults-Tabelle hinzugefügt wurden, können Sie einen SELECT * -Befehl ausführen, um alle Datensätze in der Tabelle aufzulisten, oder Spalten explizit wie folgt angeben:

SELECT Spieler-ID, Spiel-ID, Punktestand AUS Spielergebnis 

Hier sind die Ergebnisse dieser Abfrage:

spielerid gameid score ---------- ---------- ----- 1 1 82 1 2 88 1 3 78 1 4 90 1 5 85 1 6 94 2 1 10 2 2 60 2 3 50 2 4 55 2 5 45 2 6 65 3 6 100 3 5 100 3 4 100 3 3 100 3 2 100 3 1 100 

Wie Sie sehen, ist diese Auflistung nicht besonders „lesbar“..

Abfragen über mehrere Tabellen hinweg mit JOIN

Wäre es nicht hilfreicher, wenn statt der numerischen ID die Namen der Spieler und Spiele angezeigt würden? Das Abfragen und Kombinieren von Daten in SELECT-Anweisungen wird häufig durch Ausführen eines JOIN mit mehreren Tabellenquellen ausgeführt. Es gibt verschiedene Arten von JOINS. Wenn Sie mit mehreren Tabellen arbeiten, müssen Sie angeben, zu welcher Tabelle eine Spalte gehört (insbesondere, wenn Spalten den gleichen Namen haben, z. B. mit all diesen verschiedenen ID-Spalten). Sie können auf Spalten durch ihren Spaltennamen oder ihren Tabellennamen, dann einen Punkt (.) Und dann auf den Spaltennamen verweisen.

Lassen Sie uns die Spielerergebnisse erneut angeben, diesmal nur den Namen des Spiels und den Namen des Spielers. Außerdem beschränken wir unsere Ergebnisse nur auf die Punktzahl für das Finale (Spiel Nr. 6):

SELECT Players.fname || "|| Players.lname AS Spielername, Games.gamename, GameResults.score FROM GameResults JOIN Players ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid = Games.id) WHERE gameid = 6; 

Das gibt uns die folgenden Ergebnisse (Sie könnten das WO weglassen, um alle Spiele zu erhalten):

Spielername Gamename Score ------------------ -------------- ----- Bobby Fisher Final 94 Bart Simpson Finale 65 Garry Kasparov Finale 100 

Ausführen komplexerer Abfragen

Der Himmel ist das Limit, wenn es um die Abfragen geht, die Sie hier ausführen könnten. Für unser Beispiel ist die wichtigste Frage die, die uns sagt, wer das Turnier gewonnen hat.
Hier ist die letzte Abfrage zur Berechnung der Turnierrangliste:

SELECT Players.fname || "|| Players.lname AS PlayerName, SUM ((Games.weight * GameResults.score)) AS TotalWeightedScore VON GameResults JOIN Players ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid.) = Games.id) GROUP BY GameResults.playerid BESTELLEN VON TotalWeightedScore DESC; 

Diese Abfrage sammelt mithilfe von JOINs Informationen aus verschiedenen Tabellen und berechnet die Turnierergebnisse auf lesbare Weise. Schauen wir uns also an, was diese Abfrage macht:

  • Der vollständige Name jedes Spielers wird als erste Ergebnisspalte angezeigt (berechnet aus Vor- und Nachname)
  • Die Turnierpunktzahl jedes Spielers wird als zweite Ergebnisspalte angezeigt (berechnet aus den gewichteten Punktzahlen aller von einem bestimmten Spieler gespielten Spiele).
  • Die Ergebnisdatensätze werden in absteigender Reihenfolge basierend auf den Turnierergebnissen (erster Platz, zweiter Platz usw.) aufgelistet.

Die Ergebnisse dieser Abfrage werden unten gezeigt:

SpielerName TotalWeightedScore ------------------------- ----------------- Garry Kasparov 100.0 Bobby Fisher 87.5 Bart Simpson 46.25 

Fazit

Damit ist unsere Untersuchung eines einfachen SQLite-Datenbankbeispiels abgeschlossen: einer Schachturnier-Datenbank. Hoffentlich haben Sie sich wieder mit relationalen Datenbankkonzepten wie Tabellen, Datensätzen und Abfragen vertraut gemacht und sich mit vielen der häufig verwendeten SQLite-Befehle vertraut gemacht. Schließlich haben Sie den Entwurf und die Verwendung einer Beispieldatenbank durchgegangen. Nachdem Sie die Funktionsweise von SQLite-Datenbanken genau kennen, können Sie sie in Ihren Android-Anwendungen verwenden (das Thema unseres nächsten Lernprogramms in dieser Reihe)..

Über die Autoren

Die mobilen Entwickler Lauren Darcey und Shane Conder haben mehrere Bücher zur Android-Entwicklung mitgeschrieben: ein ausführliches Programmierbuch mit dem Titel Android Wireless-Anwendungsentwicklung und Sams TeachYourself Entwicklung von Android-Anwendungen in 24 Stunden. Wenn sie nicht schreiben, verbringen sie ihre Zeit damit, mobile Software in ihrem Unternehmen zu entwickeln und Beratungsdienste anzubieten. Sie können sie per E-Mail an [email protected], über ihren Blog unter androidbook.blogspot.com und über Twitter @androidwireless erreichen.