Приложения Android могут хранить данные приложений в базах данных SQLite. Из этого руководства вы узнаете, как создаются и обрабатываются базы данных SQLite.
Здесь мы начнем с разработки и использования простой базы данных SQLite для управления результатами шахматных турниров. Этот учебник предназначен для краткого обзора работы баз данных SQLite. Эти знания затем будут использованы в будущих руководствах по разработке для реализации приложений Android на основе баз данных.
Начиная
Приложения Android могут создавать и управлять своими собственными частными реляционными базами данных SQLite. Разработчики также могут проверять и изменять базы данных на заданном эмуляторе Android или устройстве, используя инструмент командной строки sqlite3, предоставляемый как часть инструмента Android SDK, называемого Android Debug Bridge (adb).
В этом руководстве мы предполагаем, что у вас есть некоторое представление о реляционных базах данных, теоретически, но вам необходимо пройти курс повышения квалификации, прежде чем использовать их в своих приложениях для Android. Этот конкретный учебник не требует каких-либо инструментов; это скорее теоретическое упражнение.
Однако, если вы планируете разрабатывать приложения для Android, основанные на базах данных SQLite, вам необходимо установить инструменты, необходимые для разработки под Android, такие как Android SDK и Eclipse IDE. Ознакомьтесь с множеством других полезных руководств по Android, доступных здесь на Mobiletuts +, чтобы помочь вам справиться с этими задачами.
Что такое SQLite?
SQLite — это легкий движок реляционных баз данных. SQLite быстр и занимает мало места, что делает его идеальным для устройств Android. Вместо мощных серверных баз данных, таких как Oracle и Microsoft SQL Server, каждая база данных SQLite хранится в одном файле на диске. Приложения Android могут хранить личные данные приложений в базе данных SQLite.
Примечание. Если вы знакомы с SQL, SQLite будет очень легко подобрать. SQLite — это в основном урезанное ядро базы данных SQL для встроенных устройств. Конкретную информацию о SQLite, его функциях, функциях и ограничениях см. В электронной документации по SQLite .
Краткий обзор основ базы данных
База данных — это просто структурированный способ постоянного хранения данных. Данные хранятся в таблицах. В таблице есть столбцы с разными типами данных. Каждая строка в таблице представляет запись данных. Возможно, вам будет полезно подумать о таблице, похожей на электронную таблицу Excel. Для перспективы объектно-ориентированного программирования каждая таблица в базе данных часто представляет объект (представленный классом). Каждый столбец таблицы представляет атрибут класса. Каждая запись в таблице представляет конкретный экземпляр этого объекта.
Давайте посмотрим на быстрый пример. Допустим, у вас есть база данных компании с таблицей «Сотрудник». Таблица Employee может иметь пять типизированных столбцов: EmployeeID (число), FirstName (строка), LastName (строка), Title (строка) и Salary (число). Затем вы можете добавить запись в базу данных для сотрудника по имени Джон Доу и отдельную запись для сотрудника по имени Энн Дроид.
Данные в базе данных предназначены для проверки и манипулирования. Данные в таблице могут быть:
- Добавлено (с помощью команды
INSERT
) - Изменено (с помощью команды
UPDATE
) - Удалено (с помощью команды
DELETE
)
Вы можете искать конкретные данные в базе данных, используя так называемый запрос. Запрос (с использованием команды SELECT) может включать одну таблицу или несколько таблиц. Чтобы создать запрос, необходимо указать интересующие таблицы, столбцы данных и значения данных с помощью языка команд SQL. Каждая команда SQL заканчивается точкой с запятой (;).
База данных шахматных турниров
Лучший способ по-настоящему понять, как работают базы данных SQLite, — это работать на простом примере, поэтому давайте сделаем это. Давайте представим, что у нас есть приложение, которое отслеживает результаты игроков в шахматном турнире. Очки игроков записываются, а затем, в конце серии матчей, определяется победитель. Общий счет каждого игрока в турнирах рассчитывается исходя из их результатов:
- Четыре разминки (вес: 10% от общего балла)
- Один полуфинал (вес: 25% от общего балла)
- Один финал (вес: 35% от общего балла)
Примечание: для турнира очки игрока могут быть основаны на формуле, которая учитывает время, необходимое для победы в игре, а также тип и количество фигур, оставшихся на доске в конце игры. Таким образом, сильный игрок получит высокий балл за то, что потерял несколько сильных фигур и быстро выиграл игру. Возможно, стиль и отношение включены судьями, чтобы поощрить веселье, легкую игру. Как рассчитываются баллы, на самом деле не важно, как мы определяем нашу базу данных; мы просто храним их в базе данных. Для простоты будем считать, что оценки основаны на шкале от 0 до 100.
Разработка схемы базы данных
Схема базы данных — это просто определение структуры базы данных в терминах таблиц, столбцов данных и тому подобного. Схема для нашей базы данных турниров довольно проста:
Схема базы данных TournamentScores содержит три таблицы:
- Таблица Players содержит информацию об игроке.
- Таблица «Игры» содержит информацию о каждой игре и о том, сколько она учитывает в общем зачете игрока за турнир.
- Таблица GameResults содержит результаты игр всех игроков.
SQLite3 поддерживает следующие распространенные типы данных для столбцов:
-
INTEGER
(целые числа со знаком) -
REAL
(значения с плавающей запятой) -
TEXT
(строка UTF-8 или UTF-16; кодируется с использованием кодировки базы данных) -
BLOB
(блок данных)
После того, как вы определили, какие столбцы необходимы для каждой таблицы, вы готовы создать несколько таблиц в схеме базы данных.
Работа с таблицами
Давайте начнем с создания таблицы игроков. Эта таблица требует уникальный идентификатор игрока для ссылки на каждого игрока. Мы можем сделать это первичным ключом (чтобы однозначно идентифицировать запись в этой таблице) и установить его атрибут автоинкремента. Автоинкремент означает, что каждый раз, когда добавляется новая запись игрока, она получает новый уникальный идентификатор игрока. Мы также хотим сохранить имя и фамилию каждого игрока — пустые значения не допускаются.
Здесь мы можем использовать SQL-оператор CREATE TABLE для генерации таблицы Players:
1
2
3
4
|
CREATE TABLE Players (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fname TEXT NOT NULL,
lname TEXT NOT NULL );
|
Игровой стол очень похож. Нам нужен уникальный идентификатор игры для ссылки на каждую игру. Мы также хотим получить понятное имя для каждой игры и весовой коэффициент, показывающий, сколько игра засчитывается в итоговый счет игрока в турнире (в процентах). Вот инструкция SQL для создания таблицы игр:
1
2
3
4
|
CREATE TABLE Games (
id INTEGER PRIMARY KEY AUTOINCREMENT,
gamename TEXT,
weight REAL DEFAULT .10 CHECK (weight<=1));
|
Вы также можете удалить таблицы с помощью оператора DROP TABLE. Например, чтобы удалить таблицу «Игры», используйте следующую команду SQL:
1
|
DROP TABLE Games;
|
Заполнение таблиц записями данных
Прежде чем мы продолжим, давайте добавим некоторые данные в эти таблицы. Чтобы добавить запись в таблицу «Игроки», необходимо указать имена столбцов и значения по порядку. Например, следующий оператор SQL использует команду INSERT для добавления записи для шахматиста Бобби Фишера:
1
2
3
4
|
INSERT into Players
(fname, lname)
VALUES
(‘Bobby’, ‘Fisher’);
|
Пока мы в этом, добавим еще двух игроков: Барт Симпсон (очень жалкий шахматист) и Гарри Каспаров (возможно, лучший шахматист когда-либо). В то же время нам нужно добавить кучу записей в таблицу игр. Сначала мы добавляем полуфинал, который рассчитывает на 25 процентов турнирной оценки игрока:
1
2
3
4
|
INSERT into Games
(gamename, weight)
VALUES
(‘Semi-Final’, .25);
|
Затем мы добавляем пару разминочных заездов, которые используют вес по умолчанию 10 процентов:
1
|
INSERT into Games (gamename) VALUES (‘Warm-up Heat 1’);
|
Наконец, мы добавляем итоговую сумму в 35 процентов от общей суммы турнира:
1
2
3
4
|
INSERT into Games
(gamename, weight)
VALUES
(‘Final’, .35);
|
Запрос таблиц для результатов с помощью SELECT
Как мы узнаем, что данные, которые мы добавили, находятся в таблице? Ну, это легко. Мы просто запрашиваем все строки в таблице, используя инструкцию SELECT:
1
|
SELECT * FROM Games;
|
Это возвращает все записи в таблице игр:
1
2
3
4
5
6
7
8
|
id gamename weight
—— ————— ——
1 Semi-Final 0.25
2 Warm-up Heat 1 0.1
3 Warm-up Heat 2 0.1
4 Warm-up Heat 3 0.1
5 Warm-up Heat 4 0.1
6 Final 0.35
|
Использование псевдонимов столбцов и вычисляемых столбцов
Мы также можем создавать свои собственные столбцы и их псевдонимы. Например, мы можем создать псевдоним столбца с именем PlayerName, который является вычисляемым столбцом: это имя и фамилия игрока, объединенные с использованием || оператор, разделенный пробелом:
1
|
SELECT fname||’
|
Этот запрос дает следующие результаты:
1
2
3
4
5
|
PlayerName id
———— —
Bobby Fisher 1
Bart Simpsen 2
Garry Kasparov 3
|
Изменение данных в таблицах
Фамилия Барта (идентификатор игрока 2) написана неправильно. Чтобы обновить таблицу Players, чтобы она отображала правильное написание, вы можете использовать команду UPDATE:
1
2
3
|
UPDATE Players
SET lname=’Simpson’
WHERE playerid=2;
|
Вы можете удалить строки из таблицы, используя функцию DELETE. Например, чтобы удалить запись, которую мы только что обновили:
1
|
DELETE FROM Players WHERE playerid=2;
|
Вы можете удалить все строки в таблице, не задав предложение WHERE:
1
|
DELETE FROM Players;
|
Использование внешних ключей и составных ключей
Теперь, когда наши игроки и игры настроены, давайте создадим таблицу GameResults. Это более сложная таблица. Таблица GameResults объединяет идентификаторы игроков из таблицы «Игроки» с идентификаторами игр из таблицы «Игры», а затем отображает счет, полученный игроком за конкретную игру. Столбцы, которые таким образом ссылаются на другие таблицы, часто называют внешними ключами. Нам нужны уникальные пары игрок-игра, поэтому мы создаем составной первичный ключ из внешних ключей игрока и игры, чтобы однозначно идентифицировать запись GameResults. Наконец, мы обеспечиваем, чтобы оценки были целыми числами от 0 до 100.
1
2
3
4
5
|
CREATE TABLE GameResults (
playerid INTEGER REFERENCES Players(id),
gameid INTEGER REFERENCES Games(id),
score INTEGER CHECK (score<=100 AND score>=0),
PRIMARY KEY (playerid, gameid));
|
(Примечание. SQLite не применяет ограничения внешнего ключа, но их можно настроить в любом случае и применить ограничения путем создания триггеров.)
Теперь пришло время вставить некоторые данные в таблицу GameResults. Допустим, Бобби Фишер (игрок с идентификатором 1) набрал 82 очка в полуфинале (игра с идентификатором 1). Вы можете использовать следующую команду SQL для вставки соответствующей записи в таблицу GameResults:
1
2
3
4
|
INSERT into GameResults
(playerid, gameid, score)
VALUES
(1,1,82);
|
Теперь давайте предположим, что турнир проводится, и результаты добавляются в таблицу GameResults. Бобби хороший игрок, Барт ужасный игрок, а Гарри всегда играет в идеальную игру. После того, как записи были добавлены в таблицу GameResults, мы можем выполнить команду SELECT *, чтобы просмотреть все записи в таблице, или мы можем явно указать столбцы следующим образом:
1
|
SELECT playerid, gameid, score FROM GameResults;
|
Вот результаты этого запроса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
playerid 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
|
Как видите, этот список не особо «читабелен».
Запросы по нескольким таблицам с помощью JOIN
Не было бы более полезным, если бы вместо их числовых идентификаторов отображались имена игроков и игр? Запросы и объединение данных в операторах SELECT часто обрабатываются путем выполнения JOIN с несколькими источниками таблиц; Существуют разные виды соединений. При работе с несколькими таблицами необходимо указать, к какой таблице принадлежит столбец (особенно, если столбцы имеют одинаковые имена, например, для всех этих различных столбцов идентификаторов). Вы можете ссылаться на столбцы по имени столбца или по имени таблицы, затем по точке (.), А затем по имени столбца.
Давайте снова подсчитаем результаты игрока, только на этот раз, включив название игры и имя игрока. Кроме того, мы ограничиваем наши результаты только счетом в Финале (идентификатор игры 6):
01
02
03
04
05
06
07
08
09
10
|
SELECT
Players.fname||’
Games.gamename,
GameResults.score
FROM GameResults
JOIN Players
ON (GameResults.playerid=Players.id)
JOIN Games
ON (GameResults.gameid=Games.id)
WHERE gameid=6;
|
что дает нам следующие результаты (вы можете оставить ГДЕ, чтобы получить все игры):
1
2
3
4
5
|
PlayerName gamename score
—————— ————— ——
Bobby Fisher Final 94
Bart Simpson Final 65
Garry Kasparov Final 100
|
Выполнение более сложных запросов
Небо это предел, когда дело доходит до запросов, которые вы могли бы выполнить здесь. Для нашего примера самый важный запрос — это тот, который сообщает нам, кто выиграл турнир.
Вот последний запрос для расчета рейтинга турнира:
01
02
03
04
05
06
07
08
09
10
|
SELECT
Players.fname||’
SUM((Games.weight*GameResults.score)) AS TotalWeightedScore
FROM GameResults
JOIN Players
ON (GameResults.playerid=Players.id)
JOIN Games
ON (GameResults.gameid=Games.id)
GROUP BY GameResults.playerid
ORDER BY TotalWeightedScore DESC;
|
Этот запрос собирает информацию из нескольких разных таблиц с помощью JOIN и вычисляет результаты турнира в удобочитаемой форме. Итак, давайте посмотрим, что делает этот запрос:
- Полное имя каждого игрока отображается в виде первого столбца результата (рассчитывается по имени и фамилии)
- Турнирная оценка каждого игрока отображается в виде второго столбца результата (рассчитывается на основе взвешенных результатов всех игр, в которые играл данный игрок)
- Записи результатов перечислены в порядке убывания на основе результатов турнира (первое место, второе место и т. Д.)
Результаты этого запроса показаны ниже:
1
2
3
4
5
|
PlayerName TotalWeightedScore
————————- ——————
Garry Kasparov 100.0
Bobby Fisher 87.5
Bart Simpson 46.25
|
Вывод
На этом мы завершаем исследование простого примера базы данных SQLite: базы данных шахматного турнира. Надеюсь, вы познакомились с понятиями реляционных баз данных, такими как таблицы, записи и запросы, и познакомились со многими из часто используемых команд SQLite. Наконец, вы прошли через дизайн и использование примера базы данных. Теперь, когда у вас есть представление о том, как работают базы данных SQLite, вы готовы использовать их в своих приложениях для Android (тема нашего следующего урока из этой серии).
Об авторах
Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android» и « Разработка Android-приложений Sams TeachYourself за 24 часа» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте [email protected] , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .