1. Code
  2. Mobile Development
  3. Android Development

SQLite-Crashkurs 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 Entwerfen und Verwenden einer einfachen SQLite-Datenbank zum Verwalten der Ergebnisse von Schachturnieren. Dieses Tutorial soll einen kurzen Überblick über die Funktionsweise von SQLite-Datenbanken geben. Dieses Wissen wird dann in zukünftigen Entwicklungs-Tutorials verwendet, um datenbankgesteuerte Android-Anwendungen zu implementieren.
Scroll to top

German (Deutsch) translation by Tatsiana Bochkareva (you can also view the original English article)

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 Entwerfen und Verwenden einer einfachen SQLite-Datenbank zum Verwalten der Ergebnisse von Schachturnieren. Dieses Tutorial soll einen kurzen Überblick über die Funktionsweise von SQLite-Datenbanken geben. Dieses Wissen wird dann in zukünftigen Entwicklungs-Tutorials verwendet, um datenbankgesteuerte Android-Anwendungen zu implementieren.

Anfangen wir

Android-Anwendungen können ihre eigenen privaten relationalen SQLite-Datenbanken erstellen und bearbeiten. Die Entwickler können Datenbanken auf einem bestimmten Android-Emulator oder -Gerät auch mit der Hilfe des Befehlszeilentools sqlite3 überprüfen und ändern, das als Teil des Android SDK-Tools Android Debug Bridge (adb) bereitgestellt wird.

In diesem Lernprogramm wird davon ausgegangen, dass Sie theoretisch ein gewisses Verständnis für relationale Datenbanken haben, jedoch einen Auffrischungskurs benötigen, bevor Sie sie in Ihren Android-Anwendungen verwenden. Für dieses spezielle Tutorial sind keine Tools erforderlich. Es ist eher eine theoretische Übung.

Wenn Sie jedoch Android-Anwendungen entwickeln möchten, 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. Schauen Sie sich die vielen anderen hilfreichen Android-Tutorials an, die hier auf Mobiletuts+ verfügbar sind, um Ihnen bei der Bearbeitung dieser Aufgaben zu helfen.

Was ist SQLite?

SQLite ist eine einfache relationale Datenbank-Engine. SQLite ist schnell und hat einen geringen Platzbedarf, was es perfekt für Android-Geräte macht. Anstelle der schwergewichtigen serverbasierten Datenbanken wie Oracle und Microsoft SQL Server wird jede SQLite-Datenbank in einer einzelnen 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 erlernen. SQLite ist im Grunde eine abgespeckte SQL-Datenbank-Engine für eingebettete Geräte. Spezifische Informationen zu SQLite und seinen Features, Funktionen und Einschränkungen finden Sie in der SQLite-Online-Dokumentation.

Ein kurzer Überblick über die Grundlagen der Datenbank

Eine Datenbank ist einfach eine strukturierte Methode zum dauerhaften Speichern von Daten. Daten werden in Tabellen gespeichert. Eine Tabelle enthält Spalten mit unterschiedlichen Datentypen. Jede Zeile in einer Tabelle repräsentiert einen Datensatz. Es kann hilfreich sein, sich eine Tabelle wie eine Excel-Tabelle vorzustellen. Für eine objektorientierte 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. Angenommen, Sie haben eine Unternehmensdatenbank mit einer Tabelle namens Mitarbeiter. Die Employee-Tabelle kann fünf typisierte Spalten enthalten: EmployeeID (Nummer), Vorname (Zeichenfolge), Nachname (Zeichenfolge), Titel (Zeichenfolge) und Gehalt (Nummer). Sie können dann der Datenbank einen Datensatz für einen Mitarbeiter namens John Doe und einen separaten Datensatz für einen Mitarbeiter namens Anne Droid hinzufügen.

Daten in einer Datenbank sollen überprüft und manipuliert werden. Daten einer Tabelle können innerhalb sein:

  • Hinzugefügt (mit dem Befehl INSERT)
  • Geändert (mit dem Befehl UPDATE)
  • Entfernt (mit dem Befehl DELETE)

Sie können innerhalb einer Datenbank nach bestimmten Daten suchen, indem Sie eine sogenannte Abfrage verwenden. Eine Abfrage (mit dem Befehl SELECT) kann eine Tabelle 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 Datenbank für Schachturniere

Der beste Weg, um wirklich zu verstehen, wie SQLite-Datenbanken funktionieren, besteht darin, ein einfaches Beispiel durchzuarbeiten. Stellen wir uns vor, wir haben eine Anwendung, mit der die Spielergebnisse eines Gelegenheitsschachturniers erfasst werden. Die Spielergebnisse werden aufgezeichnet und am Ende einer Reihe von Spielen wird der Gewinner ermittelt. Die Gesamtpunktzahl eines jeden Spielers wird aus seiner Leistung berechnet auf:

  • Vier Aufwärmlä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 die Spielergebnisse auf einer Formel basieren, die die Zeit berücksichtigt, die zum Gewinnen des Spiels benötigt wurde, sowie die Art und Anzahl der am Ende des Spiels auf dem Brett verbleibenden Spielsteine. Auf diese Weise erhält ein starker Spieler eine hohe Punktzahl, wenn er wenige mächtige Teile verliert und das Spiel schnell gewinnt. Vielleicht werden Stil und Haltung von den Richtern aufgenommen, um Spaß und leichtes Spielen zu fördern. Wie die Punktzahlen berechnet werden, ist für die Definition unserer Datenbank nicht wichtig. Wir speichern sie einfach in der Datenbank. Der Einfachheit halber nehmen wir an, dass die Bewertungen auf einer Skala von 0 bis 100 basieren.

Entwerfen des Datenbankschemas

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

Das TournamentScores-Datenbankschema enthält drei Tabellen:

  • Die Spielertabelle enthält Spielerinformationen.
  • Die Spieletabelle enthält Informationen zu jedem Spiel und wie viel es für die Gesamtturnierpunktzahl des Spielers zählt.
  • Die GameResults-Tabelle enthält die Spielergebnisse aller Spieler.

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

  • INTEGER (vorzeichenbehaftete Ganzzahlen)
  • REAL (Gleitkommawerte)
  • TEXT (UTF-8- oder UTF-16-Zeichenfolge; codiert mit Datenbankcodierung)
  • BLOB (Datenblock)

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

Arbeiten mit Tabellen

Beginnen wir mit der Erstellung der Players-Tabelle. Für diese Tabelle ist eine eindeutige Spieler-ID erforderlich, um auf jeden Spieler zu verweisen. Wir können dies zum Primärschlüssel machen (um einen Datensatz in dieser Tabelle eindeutig zu identifizieren) und sein Autoincrement-Attribut festlegen. Autoincrement bedeutet, dass jedes Mal, wenn ein neuer Spielerdatensatz hinzugefügt wird, der Datensatz eine neue, eindeutige Spieler-ID erhält. Wir möchten auch den Vor- und Nachnamen jedes Spielers speichern - keine Nullen erlaubt.
Hier können wir die SQL-Anweisung CREATE TABLE verwenden, um die Players-Tabelle zu generieren:

1
CREATE TABLE Players (
2
id INTEGER PRIMARY KEY AUTOINCREMENT,
3
fname TEXT NOT NULL,
4
lname TEXT NOT NULL );

Der Spieltisch ist sehr ähnlich. Wir benötigen eine eindeutige Spiel-ID, um auf jedes Spiel zu verweisen. Wir möchten auch einen Anzeigenamen für jedes Spiel und einen Gewichtswert dafür, wie viel das Spiel für die endgültige Turnierpunktzahl des Spielers zählt (in Prozent). Hier ist die SQL-Anweisung zum Erstellen der Spieletabelle:

1
CREATE TABLE Games (
2
id INTEGER PRIMARY KEY AUTOINCREMENT,
3
gamename TEXT,
4
weight REAL DEFAULT .10 CHECK (weight
5
You can also delete tables using the DROP TABLE statement. For example, to delete the Games table, use the following SQL command:
6
DROP TABLE Games;
7
 Populating Tables with Data Records Before we move on, let’s add some data to these tables. To add a record to the Players table, you need to specify the column names and the values in order. For example, the following SQL statement uses the INSERT command to add a record for chess player Bobby Fisher: INSERT into Players
8
(fname, lname)
9
VALUES
10
('Bobby', 'Fisher');
11
 While we’re add it, we’ll add two more players: Bart Simpson (a very pitiful chess player) and Garry Kasparov (perhaps the best chess player ever). At the same time, we need to add a bunch of records to the Games table. First we add the semi-final, which counts for 25 percent of the player’s tournament score: INSERT into Games
12
(gamename, weight)
13
VALUES
14
('Semi-Final', .25);
15
 Then we add a couple warm-up heats, which use the default weight of 10 percent: INSERT into Games (gamename) VALUES ('Warm-up Heat 1');
16
 Finally, we add a final worth 35 percent of the total tournament score: INSERT into Games
17
(gamename, weight)
18
VALUES
19
('Final', .35);
20
 Querying Tables for Results with SELECT How do we know the data we’ve added is in the table? Well, that’s easy. We simply query for all rows in a table using a SELECT statement: SELECT * FROM Games;
21
 This returns all records in the Games table: id     gamename         weight
22
-----  ---------------  ------
23
1      Semi-Final       0.25
24
2      Warm-up Heat 1   0.1
25
3      Warm-up Heat 2   0.1
26
4      Warm-up Heat 3   0.1
27
5      Warm-up Heat 4   0.1
28
6      Final            0.35
29
 Using Column Aliases and Calculated Columns We can also create our own columns and alias them. For example, we can create a column alias called PlayerName that is a calculated column: It’s the player’s first and last names concatenated using the || operator, separated by a space: SELECT fname||' '|| lname AS PlayerName, id FROM Players;
30
 This query produces the following results: PlayerName        id
31
------------      --
32
Bobby Fisher      1
33
Bart Simpsen      2
34
Garry Kasparov    3
35
 Altering Data in Tables Bart’s (player id 2) last name is spelled incorrectly. To update the Players table to reflect the correct spelling, you can use the UPDATE command: UPDATE Players
36
SET lname='Simpson' 
37
WHERE playerid=2;
38
 You can delete rows from a table using the DELETE function. For example, to delete the record we just updated: DELETE FROM Players WHERE playerid=2;
39
 You can delete all rows in a table by not specifying the WHERE clause: DELETE FROM Players;
40
 Using Foreign Keys and Composite Keys Now that we have our Players and Games all set up, let’s create the GameResults table. This is a more complicated table. The GameResults table pairs up player ids from the Players table with game ids from the Games table and then lists the score that the player earned for the specific game. Columns, which link to other tables in this way, are often called foreign keys. We want unique player-game pairings, so we create a composite primary key from the player and game foreign keys, to uniquely identify a GameResults record. Lastly, we enforce that the scores are whole numbers between 0 and 100. CREATE TABLE GameResults (
41
playerid INTEGER REFERENCES Players(id), 
42
gameid INTEGER REFERENCES Games(id),
43
score INTEGER CHECK (score=0),
44
PRIMARY KEY (playerid, gameid));
45
 (Note: SQLite does not enforce foreign key constraints, but you can set them up anyway and enforce the constraints by creating triggers.) Now it’s time to insert some data to the GameResults table. Let’s say Bobby Fisher (player id 1) received a score of 82 points on the semi-final (game id 1). You could use the following SQL command to insert the appropriate record into the GameResults table: INSERT into GameResults
46
(playerid, gameid, score)
47
VALUES
48
(1,1,82);
49
 Now let’s assume the tournament is played and the scores are added to the GameResults table. Bobby is a good player, Bart is a terrible player, and Garry always plays a perfect game. Once the records have been added to the GameResults table, we can perform a SELECT * command to list all records in the table, or we can specify columns explicitly like this: SELECT playerid, gameid, score FROM GameResults;
50
 Here are the results from this query: playerid   gameid      score
51
----------  ----------  -----
52
1           1           82
53
1           2           88
54
1           3           78
55
1           4           90
56
1           5           85
57
1           6           94
58
2           1           10
59
2           2           60
60
2           3           50
61
2           4           55
62
2           5           45
63
2           6           65
64
3           6           100
65
3           5           100
66
3           4           100
67
3           3           100
68
3           2           100
69
3           1           100
70
 As you can see, this listing is not particularly “human-readable”. Querying Across Multiple Tables Using JOIN Wouldn’t it be more helpful if the names of the players and Games were shown instead of their numeric ids? Querying and combining data in SELECT statements is often handled by performing a JOIN with multiple table sources; there are different kinds of JOINS. When you work with multiple tables, you need to specify which table that a column belongs to (especially when columns are named the same, such as with all these different id columns). You can refer to columns by their column name or by their table name, then a dot (.), and then the column name. Let’s relist the player scores again, only this time, include the name of the game and the name of the player. Also, we limit our results only to the score for the Final (game id 6): SELECT
71
Players.fname||' '|| Players.lname AS PlayerName,
72
Games.gamename,
73
GameResults.score
74
FROM GameResults
75
JOIN Players
76
        ON (GameResults.playerid=Players.id)
77
JOIN Games
78
        ON (GameResults.gameid=Games.id)
79
WHERE gameid=6;
80
 which gives us the following results (you could leave off the WHERE to get all Games): PlayerName           gamename        score
81
------------------   --------------  -----
82
Bobby Fisher         Final           94
83
Bart Simpson         Final           65
84
Garry Kasparov       Final           100
85
 Executing More Complex Queries The sky’s the limit when it comes to the queries you could perform here. For our example, the most important query is the one that tells us who won the tournament. Here is the final query for calculating the tournament rankings: SELECT
86
Players.fname||' '|| Players.lname AS PlayerName,
87
SUM((Games.weight*GameResults.score)) AS TotalWeightedScore
88
FROM GameResults
89
JOIN Players
90
        ON (GameResults.playerid=Players.id)
91
JOIN Games
92
        ON (GameResults.gameid=Games.id)
93
GROUP BY GameResults.playerid
94
ORDER BY TotalWeightedScore DESC;
95
 This query gathers information from several different tables using JOINs and calculates the tournament results in a readable way. So let’s look at what this query does: 
  • Der vollständige Name jedes Spielers wird als erste Ergebnisspalte angezeigt (berechnet aus seinem Vor- und Nachnamen).
  • Die Turnierergebnisse jedes Spielers werden als zweite Ergebnisspalte angezeigt (berechnet aus den gewichteten Ergebnissen 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 angezeigt:

1
PlayerName                 TotalWeightedScore
2
-------------------------  -----------------
3
Garry Kasparov             100.0
4
Bobby Fisher               87.5
5
Bart Simpson               46.25

Abschluss

Damit ist unsere Untersuchung eines einfachen SQLite-Datenbankbeispiels abgeschlossen: einer Schachturnierdatenbank. Hoffentlich haben Sie sich erneut 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 das Design und die Verwendung einer Beispieldatenbank beschrieben. Nachdem Sie nun einen Überblick über die Funktionsweise von SQLite-Datenbanken erhalten haben, können Sie diese in Ihren Android-Anwendungen verwenden (das Thema unseres nächsten Tutorials in dieser Reihe).

Über die Autoren

Die Entwickler von Mobilgeräten Lauren Darcey und Shane Conder haben mehrere Bücher zur Android-Entwicklung verfasst: ein ausführliches Programmierbuch mit dem Titel Android Wireless Application Development und Sams TeachYourself Android Application Development 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 per E-Mail an androidwirelessdev+mt@gmail.com, über ihren Blog unter androidbook.blogspot.com und auf Twitter @androidwireless erreicht werden.

Benötigen Sie weitere Hilfe beim Schreiben von Android Apps? Schauen Sie sich unsere neuesten Bücher und Ressourcen an!

Buy Android Wireless Application Development, 2nd Edition Buy Sam's Teach Yourself Android Application Development in 24 Hours Mamlambo code at Code Canyon