- Полный список
- Использование простой базы данных SQLite в Android-приложении
- Что такое SQLite
- Подготовка
- Описание примера приложения
- Классы хранения базы данных SQLite
- Определение таблиц
- Создание базы данных с помощью SQLiteOpenHelper
- Выбор данных из базы данных SQLite
- Отображение содержимого объекта Cursor в RecyclerView
- Определение внешних ключей
- Обновление SQLiteOpenHelper
- Отображение данных из запроса SQLite в Spinner
- Вставка внешнего ключа в базу данных
- Выборка данных из базы SQLite с помощью JOIN
- В заключении
Полный список
— подробно разбираем метод чтения данных query
— используем сортировку, группировку, условия, having
На прошлых уроках мы использовали метод query для чтения всех данных из таблицы. Мы использовали только имя таблицы в качестве входного параметра и получали все записи. Но у query есть и другие параметры:
columns – список полей, которые мы хотим получить
selection – строка условия WHERE
selectionArgs – массив аргументов для selection. В selection можно использовать знаки ?, которые будут заменены этими значениями.
groupBy — группировка
having – использование условий для агрегатных функций
orderBy — сортировка
Попробуем на примере их использовать. Создадим приложение – справочник стран. Возьмем десять стран и сохраним в БД их наименование, количество населения и регион. Реализуем в приложении следующие функции:
— вывод всех записей
— вывод значения агрегатной функции (SUM, MIN, MAX, COUNT)
— вывод стран с населением, больше чем указано
— группировка стран по региону
— вывод регионов с населением больше, чем указано
— сортировка стран по наименованию, населению или региону
Выводить все данные снова будем в лог.
Project name: P0361_SQLiteQuery
Build Target: Android 2.3.3
Application name: SQLiteQuery
Package name: ru.startandroid.develop.p0361sqlitequery
Create Activity: MainActivity
Открываем layout-файл main.xml и пишем:
6 кнопок – 6 функций, которые мы планируем реализовать. Поля для ввода значений, где это необходимо. Для сортировки используем RadioGroup.
Код для MainActivity.java:
Никаких проверок на вводимые с экрана значения я не делал, чтобы не перегружать код. Он и так немаленький получился, но ничего сложного в нем нет.
Три массива данных name, people, region. Это наименования стран, их население (в млн.) и регионы, к которым страны относятся. По этим данным мы будем заполнять таблицу.
В методе onCreate мы определяем и находим экранные элементы, присваиваем обработчики, создаем объект dbHelper для управления БД, подключаемся к базе и получаем объект db для работы с БД, проверяем наличие записей в таблице, если нет ничего – заполняем ее данными, закрываем соединение и эмулируем нажатие кнопки Все записи — чтобы сразу вывести весь список.
В методе onClick – подключаемся к базе, читаем данные с экранных полей в переменные, описываем переменные, которые будем использовать в методе query, и курсор, и смотрим, какая кнопка была нажата.
btnAll – вывод всех записей. Вызываем метод query с именем таблицы и null для остальных параметров. Это уже знакомо, делали на прошлом уроке.
btnFunc – вывод значения агрегатной функции (или любого поля). Использую параметр columns, в который надо записать поля, которые я хотел бы получить из таблицы, т.е. то, что обычно перечисляется после слова SELECT в SQL-запросе. columns имеет тип String[] – массив строк. Создаем массив из одного значения, которое считано с поля etFunc на экране. Запускаем query.
btnPeople – вывод стран с населением больше введенного на экране количества. Используем selection для формирования условия. При этом используем один аргумент — ?. Значение аргумента задаем в selectionArgs – это sPeople – содержимое поля etPeople. Запускаем query.
btnGroup – группировка стран по регионам и вывод общее количество населения. Используем columns для указания столбцов, которые хотели бы получить – регион и сумма населения. В groupBy указываем, что группировка будет по региону. Запускаем query.
btnHaving – вывод регионов с населением больше указанного числа. Полностью аналогично случаю с группировкой, но добавляется условие в параметре having – сумма населения региона должна быть меньше sRegionPeople (значение etRegionPeople с экрана).
btnSort – сортировка стран. Определяем какой RadioButton включен и соответственно указываем в orderBy поле для сортировки данных. Запускаем query.
В выше описанных случаях мы запускали query и получали объект c класса Cursor. Далее мы проверяем, что он существует и в нем есть записи (moveToFirst). Если все ок, то мы запускаем перебор записей в цикле do … while (c.moveToNext()). Для каждой записи перебираем названия полей (getColumnNames), получаем по каждому полю его номер и извлекаем данные методом getString. Формируем список полей и значений в переменную str, которую потом выводим в лог. После всего этого закрываем соединение.
Ну и в конце кода идет описание вложенного класса DBHelper. Тут ничего не изменилось с прошлых уроков. Только при создании таблицы используются другие поля.
Сохраняем все и запускаем приложение.
В лог при запуске вывелись все записи, как если бы мы нажали кнопку «Все записи».
— Все записи —
name = Китай; people = 1400; region = Азия;
name = США; people = 311; region = Америка;
name = Бразилия; people = 195; region = Америка;
name = Россия; people = 142; region = Европа;
name = Япония; people = 128; region = Азия;
name = Германия; people = 82; region = Европа;
name = Египет; people = 80; region = Африка;
name = Италия; people = 60; region = Европа;
name = Франция; people = 66; region = Европа;
name = Канада; people = 35; region = Америка;
Т.е. таблица заполнена данными, можно работать.
Попробуем использовать агрегатную функцию. Например – получим кол-во записей. Вводим значение:
жмем кнопку Функция. Смотрим лог:
— Функция count(*) as Count —
Count = 10;
Все верно, 10 записей в таблице.
Покажем страны с населением больше 100 млн. Вводим 100 и жмем Население >
— Население больше 100 —
name = Китай; people = 1400; region = Азия;
name = США; people = 311; region = Америка;
name = Бразилия; people = 195; region = Америка;
name = Россия; people = 142; region = Европа;
name = Япония; people = 128; region = Азия;
Сгруппируем страны по региону и покажем население регионов. Нажмем кнопку Население по региону
— Население по региону —
region = Азия; people = 1528;
region = Америка; people = 541;
region = Африка; people = 80;
region = Европа; people = 350;
Теперь отобразим только те регионы, в которых население выше 500 млн.чел. Вводим 500 и жмем Население по региону >
— Регионы с населением больше 500 —
region = Азия; people = 1528;
region = Америка; people = 541;
Осталась сортировка. Выберем, например, сортировку по населению и жмем кнопку Сортировка
— Сортировка по населению —
name = Канада; people = 35; region = Америка;
name = Италия; people = 60; region = Европа;
name = Франция; people = 66; region = Европа;
name = Египет; people = 80; region = Африка;
name = Германия; people = 82; region = Европа;
name = Япония; people = 128; region = Азия;
name = Россия; people = 142; region = Европа;
name = Бразилия; people = 195; region = Америка;
name = США; people = 311; region = Америка;
name = Китай; people = 1400; region = Азия;
По умолчанию сортировка идет по возрастанию.
Все работает так, как и должно. На этих примерах мы использовали все основные параметры метода query. Кроме описанных параметров, у метода query есть также реализации с использованием параметров limit и distinct. Я не стал их здесь отдельно показывать. Расскажу на словах:
limit – строковый параметр, указывается в формате [offset], rows. Т.е. если в query в качестве limit передать строку «5» — то запрос выдаст только пять первых записей. Если же передать «3,5«, то запрос выдаст пять записей, начиная с четвертой (НЕ с третьей).
distinct – это boolean-параметр, удаление дубликатов. Может быть true или false.
Надеюсь, что метод query, который сначала казался большим скоплением параметров, стал понятен и прост.
На следующем уроке:
— читаем данные из связанных таблиц
— используем rawQuery
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Использование простой базы данных SQLite в Android-приложении
В этом руководстве я подробно расскажу о том, как использовать базу данных Android SQLite .
Что такое SQLite
SQLite — это система управления реляционными базами данных, похожая на Oracle , MySQL , PostgreSQL и SQL Server . Она реализует большую часть стандарта SQL , но в отличие от четырех упомянутых выше СУБД она не поддерживает модель « клиент-сервер ». Скорее, она встроена в конечную программу. Это означает, что можно связать базу данных SQLite с приложением и получить доступ ко всем возможностям БД в своем приложении.
Данная СУБД совместима как с Android , так и с iOS , и каждое приложение может создавать и использовать базу данных SQLite . В Android контакты и медиа хранятся и ссылаются на БД SQLite . Она является наиболее используемой СУБД в мире и самым распространенным программным обеспечением . Чтобы узнать о базах данных SQLite как можно больше, посетите официальный сайт SQLite .
Подготовка
Чтобы включить привязку данных в приложении, нужно добавить в файл build.gradle следующий код:
Чтобы использовать как RecyclerView , так и CardView для отображения списков, нужно включить соответствующие библиотеки в разделе зависимостей в файле build.gradle :
Чтобы задействовать все возможности базы данных SQLite , лучше изучить синтаксис SQL .
Описание примера приложения
В нашем Android SQLite примере мы создадим две таблицы: Employer и Employee . Таблица Employee будет содержать ссылку на внешний ключ таблицы Employer . Мы рассмотрим, как вставлять, выбирать, обновлять и удалять строки из таблиц. Я также продемонстрирую, как вывести элементы, выбранные из базы данных SQLite в RecyclerView ( список ) и в Spinner .
У нас есть MainActivity , из которого можно перейти к EmployerActivity ( для работы с таблицей Employer ) или к EmployeeActivity ( для работы с таблицей Employee ):
Классы хранения базы данных SQLite
Классы определяют то, как данные хранятся в базе. SQLite сохраняют значения с помощью пяти доступных классов хранения:
- NULL — нулевое значение;
- INTEGER — для целых чисел, содержащих от 1 до 8 байтов;
- REAL — числа с плавающей запятой;
- TEXT — текстовые строки, хранящиеся с использованием кодировки базы данных ( UTF-8 или UTF-16 );
- BLOB — двоичные данные, хранящиеся точно так, как они были введены.
Определение таблиц
Поскольку база данных SQLite является локальной, нужно обеспечить, чтобы приложение создавало таблицы и по мере необходимости сбрасывало их.
Начнем с Android SQLite query создания таблицы Employer , а затем перейдем к EmployerActivity .
Рекомендуется размещать логику создания базы х SQLite в классе. Это облегчает устранение возможных неполадок. Назовем наш класс SampleDBContract :
Мы определяем частный конструктор для SampleDBContract , а затем создаем класс для представления таблицы Employer . Обратите внимание: класс Employer реализует интерфейс BaseColumns . Он предоставляет два столбца в нашей таблице. Это столбец _ID , который будет автоматически увеличиваться при добавлении каждой новой строки. И столбец _COUNT , который может использоваться ContentProviders для возврата количества записей, извлекаемых через запрос. Столбец _COUNT не является обязательным. Строка CREATE_TABLE компилируется в следующий оператор SQL :
На данный момент в нашем Android SQLite примере мы определили схему таблицы Employer .
Создание базы данных с помощью SQLiteOpenHelper
Самый простой способ управления созданием базы данных и версиями — создать подкласс SQLiteOpenHelper . Он упрощает управление базой данных SQLite , создавая БД, если они не существуют. Необходимо только переопределить методы onCreate() и onUpgrade() , чтобы указать нужное действие для создания или обновления базы данных:
Теперь в нашем примере Android database SQLite задаем для нашей базы данных SQLite имя ( sample_database ). Конструктор вызывает конструктор суперкласса с именем и версией базы данных. В onCreate мы указываем объекту SQLiteDatabase выполнить оператор Employer CREATE_TABLE SQL . Через onUpgrade мы сбрасываем таблицу Employer и создаем ее снова:
Таблица Employer имеет три столбца: name , description и founded_date . Нажатие кнопки сохранения вызывает метод saveToDB() :
В saveToDB() мы получаем ссылку на объект SQLiteDatabase , используя метод getWritableDatabase() из SQLiteOpenHelper . Этот метод создает базу данных, если она еще не существует, или открывает ее, если она уже создана. GetWritableDatabase возвращает объект SQLiteDatabase , который открывает доступ на чтение / запись:
В приведенном выше фрагменте кода есть четыре момента:
- Мы получаем объект SQLiteDatabase , который открывает доступ на запись в базу данных;
- Значения, которые будут храниться в базе данных, помещаются в объект ContentValue с именем столбца в качестве ключа;
- Мы помещаем Date в объект ContentValue , который переводится в класс хранения данных Android SQLite INTEGER ;
- При вставке строки в базу данных с помощью метода database.insert() возвращается идентификатор строки.
Выбор данных из базы данных SQLite
Подобно тому, как мы применили метод getWritableDatabase() , можно вызвать getReadableDatabase() объекта SQLiteOpenHelper для получения объекта SQLiteDatabase , который можно использовать для чтения информации из базы данных. Стоит отметить, что объект SQLiteDatabase , возвращаемый getReadableDatabase() , предоставляет собой тот же самый доступ на чтение / запись в базу данных, который был возвращен функцией getWritableDatabase() , за исключением тех случаев, когда существуют определенные ограничения. Например, файловая система, содержащая заполненную базу данных, и база данных может быть открыта только для чтения.
Метод readFromDB будет запрашивать БД, и возвращать все строки из таблицы Employer , в которых имя или описание из таблицы Employer совпадает со значением, введенным в EditText . А также строки, в которых дата основания компании совпадает со значением, введенным в EditText :
В коде Android SQLite query , приведенного выше, projection является массивом String , представляющим столбцы, которые мы хотим получить. selection является строковым представлением условия SQL WHERE , отформатированным таким образом, что символ ‘?’ будет заменен аргументами в массиве selectionArgs String . Вы также можете группировать, фильтровать и сортировать результаты запроса. Вставка данных в базу SQLite с использованием описанного выше метода защищает от SQL-инъекций .
Обратите внимание на объект, возвращаемый запросом — Cursor . В следующем разделе мы покажем, как вывести содержимое Cursor с помощью RecyclerView .
Отображение содержимого объекта Cursor в RecyclerView
Cursor предоставляет произвольный доступ к набору результатов, возвращаемому запросом к базе данных. Это означает, что через Cursor можно получить доступ к значениям в любом месте, подобно Java-спискам или массивам. Благодаря этому приему можно реализовать RecyclerView с использованием Cursor так же, как мы реализуем RecyclerView с помощью ArrayLists . Вместо вызова List.get(i) , вы перемещаете Cursor в нужную позицию, используя moveToPosition() . После этого вызываете соответствующий метод getXXX(int columnIndex) , где XXX — это Blob , Double , Float , Int , Long , Short или String .
Чтобы не беспокоиться о корректных индексах столбцов из метода readFromDB() , примененного выше, мы используем метод getColumnIndexOrThrow() , который извлекает индекс указанного столбца или генерирует исключение, если имя столбца не существует внутри объекта Cursor :
Определение внешних ключей
На данный момент в нашем Android SQLite примере мы создали таблицу Employer , которую заполнили строками. Теперь создадим таблицу Employee , которая связана с таблицей Employer через столбец _ID Employer . Мы определяем класс Employee , который расширяет BaseColumns в классе SampleDBContract . Обратите внимание, что при создании таблицы Employee использовали « FOREIGN KEY(employer_id) REFERENCES employer(_id) «:
Обновление SQLiteOpenHelper
На данный момент в Android Studio SQLite у вас должна быть создана таблица Employer и в нее добавлены значения. Если вы не изменяете версию базы данных, новая таблица Employee не будет создана. К сожалению, если вы измените версию через повторный вызов метода onUpgrade() , то таблица Employer будет сброшена. Чтобы предотвратить это, можно закомментировать или удалить оператор drop в методе onUpgrade() и добавить оператор execSQL() для создания таблицы Employee . Поскольку таблица Employee ссылается на таблицу Employer , сначала необходимо создать таблицу Employer :
Отображение данных из запроса SQLite в Spinner
Чтобы создать работника в таблице Employee , пользователю необходимо выбрать соответствующего работодателя в таблице Employer . Для этого можно предоставить пользователю Spinner . Отобразить содержимое Cursor в Spinner довольно просто.
Сначала мы выполняем Android SQLite query , как было описано выше, выбираем только name из Employer и id (queryCols) . Затем создаем экземпляр SimpleCursorAdapter , передавая ему Cursor , массив столбцов для отображения ( adapterCols ) и массив представлений, с помощью которых должны отображаться столбцы ( adapterRowViews ). Затем устанавливаем Spinner Adapter для SimpleCursorAdapter :
Вставка внешнего ключа в базу данных
Вставка строки, содержащей внешний ключ, полностью идентична вставке строк в таблицу без ограничений по внешнему ключу. Разница заключается в том, что в Android SQLite примере мы получаем ссылку на выбранный объект Cursor из Spinner , а затем — значение столбца _ID Employer :
Выборка данных из базы SQLite с помощью JOIN
Нельзя использовать метод SQLiteDatabase query() для выполнения запроса к нескольким таблицам. Для этого нужно составить собственный SQL-запрос . В приведенном ниже примере запрос определяется в классе SampleDBContract :
Обратите внимание, что в условии WHERE мы используем символ « ? ». Чтобы не нарушить синтаксис SQL нужно определить selectArgs String [] со значениями, которые будут заменять в предоставленном SQL-запросе символ « ? »:
В заключении
Полная версия исходного кода доступна на github для использования и изменения. Базы данных Android SQLite — это мощное средство, доступное для всех мобильных приложений.
Дайте знать, что вы думаете по этой теме статьи в комментариях. Мы крайне благодарны вам за ваши комментарии, лайки, подписки, дизлайки, отклики!
Дайте знать, что вы думаете по данной теме в комментариях. За комментарии, отклики, подписки, лайки, дизлайки низкий вам поклон!
Источник