Статьи

Android SDK: Управление базами данных Multi-Table Sqlite3

Этот учебник предоставит интерактивное приложение для создания и управления базами данных из нескольких таблиц для устройств Android. Будут предоставлены возможности навигации и поиска в базе данных, а также всплывающее окно ввода запроса, которое будет принимать запросы произвольной формы и отображать результаты в поле прокрутки.

SQLite3 — это легкая транзакционная база данных с небольшими требованиями к дисковому пространству и памяти. Он широко используется в мобильных операционных системах, таких как Android, iPhone и т. Д. Это теперь полностью реляционная база данных с поддержкой внешних ключей.

База данных обычно содержит одну или несколько таблиц. Таблицы предназначены для хранения данных четырех типов: Integer, Real, String и Blob (двоичные или большие данные). Есть много хороших руководств по созданию и управлению базой данных одной таблицы.

Для полного обсуждения основ создания таблиц, проверьте:

Поскольку Android не предоставляет менеджера интерфейса базы данных, эти учебные пособия учат нас эффективным способам создания и управления базой данных из одной таблицы.

По сути, необходимы следующие шаги:

1. Сначала определяется класс Database Helper, который расширяется из класса SQLiteOpenHelper. Это помогает в создании или открытии базы данных, обновлении базы данных и определении таблиц, столбцов, индексов, триггеров и представлений для базы данных.

2. Используя этот вспомогательный класс, создается класс адаптера базы данных, в котором запрограммированы базовые инструменты управления базами данных CRUD (создание, чтение, обновление и удаление).

3. SQL-запросы используются для управления операциями CRUD. Поиск данных осуществляется с использованием курсоров.
Реальные базы данных обычно имеют более одной таблицы. Это создает проблему при создании и управлении таблицами.

Ниже приводится стандартная процедура для проектирования базы данных с несколькими таблицами:

1. Поскольку база данных смонтирована на устройстве Android, после ее создания ее нельзя изменить на устройстве телефона. Изменения требуют ручного вмешательства, такого как удаление базы данных с устройства, изменение с помощью Sqlite3 Manager и перемонтирование на устройстве телефона.

2. Все таблицы должны быть созданы одновременно в функции onCreate вспомогательного класса базы данных. Эта функция вызывается, когда создается экземпляр класса адаптера базы данных. Каждая таблица должна иметь свой собственный SQL создания. Команда execSql должна выполняться для каждой таблицы отдельно.

3. Как мы управляем этими таблицами? Нужны ли отдельные адаптеры для каждой таблицы? Если у кого-то есть большое количество таблиц, перегрузка адаптера будет огромной. К сожалению, большинство опубликованных руководств посвящено этому подходу.

Не было бы неплохо создать базу данных, множество таблиц и управлять ими с помощью единого интерфейса адаптера? Да будет. В этом руководстве будет описан такой дизайн базы данных с двумя графическими пользовательскими интерфейсами Android (GUI) с использованием двух классов активности Android. Первое действие, StartIntMulti, предоставляет простой пользовательский интерфейс ввода, в который будут вводиться базы данных и схемы таблиц. После завершения ввода вторая операция, ManageIntMulti, обеспечивает базовое управление CRUD и возможность навигации по таблице с поиском с использованием только одного класса адаптера базы данных. Также предусмотрено поле ввода запроса, в котором любой запрос может выполняться независимо от выбранного интерфейса таблицы.

В этом руководстве предполагается, что читатель знаком с созданием и управлением базой данных одной таблицы. Мы будем следовать хорошему примеру многостоловой базы данных из Android Sqlit .

Давайте начнем с первого графического интерфейса, показанного ниже.

GUI интерфейс

Это интерфейс, необходимый для создания интерактивной базы данных. Управление данными осуществляется через класс DataAttrib. Этот класс имеет различные члены, которые помогают в хранении и извлечении входных данных.

Первые два поля ввода требуют ввода имени базы данных и номера версии. Давайте введем ChessDb в качестве имени базы данных и 1 в качестве номера версии. Нажмите на кнопку Новая база данных, чтобы сохранить входные данные. Ввод сохраняется через функции класса setDbName и setDbVersion. Член класса setDbStatus сохраняет «новый» или «старый» статус базы данных (для ранее созданной базы данных используйте кнопку «Старая база данных» и кнопку «Запуск базы данных» для перехода к следующей операции).

Следующие три поля ввода принимают имя таблицы. Для наших целей введите «Players» в качестве имени таблицы. Имена таблиц сохраняются в массиве tbl_Names [], а количество таблиц записывается в setNumTables.

Следующие два поля ввода принимают имя поля и поля ввода. Первое поле каждой таблицы — «_id», которое является целочисленным типом. Это первичный ключ, который автоматически увеличивается. Он запрограммирован автоматически и не требует ввода. В поле имени введите «fname» в качестве ввода имени поля и «text» в качестве ввода типа (не используйте «» в полях ввода). Значение «not null» используется по умолчанию в самой программе. Имя поля и тип поля сохраняются в двумерных массивах, Col_Names [] [] и Col_Types. Количество столбцов записывается в массиве Ncols [].

Нажмите кнопку «Добавить поле», чтобы сохранить ввод. Это очищает поле Имя поля. Теперь в том же поле ввода Имя поля введите переменную второго поля «lname». Обязательно очистите поле ввода перед вводом новых входов. Тип ввода — это «текст». Нажмите кнопку Добавить поле еще раз. Поскольку мы закончили с первым определением таблицы, мы нажмем кнопку «Создать таблицу». Не нажимайте эту кнопку, если все поля не были определены.

Дизайн стола

«Каскадное удаление» должно быть «на удаленном каскаде» в последней строке. Обратите внимание, что я изменил структуру таблиц по сравнению с той, которая определена в ссылке, чтобы обеспечить соответствие таблиц. Если вам нужен составной первичный индекс, вы можете создать эту таблицу через графический интерфейс создателя запросов в следующем интерфейсе.

Это все на данный момент. Если у вас есть больше таблиц, вы можете ввести таким же образом. За кулисами программирования стоит довольно стандартное Java-программирование для приложений Android. Данные сохраняются в классе DatabaseAttrib. Посмотрите на структуру этого класса. Он состоит из основной функции получения и установки для входов, описанных выше. Нажмите кнопку Launch Database, чтобы перейти на следующий уровень управления базой данных.

В следующем графическом интерфейсе показан класс активности управления базой данных:

графический интерфейс пользователя

Давайте рассмотрим общий процесс управления базой данных. Когда пользователь запускает новую или старую базу данных, эта операция, ManageIntMulti, получает всю информацию о таблицах, именах и типах полей из класса DataAttrib. В самом верху графического интерфейса, кроме надписей TextBox, находится интерфейс управления селектором таблиц Spinner. Элемент управления Spinner заполняется именами этих таблиц. Это радио-кнопка управления, где только один элемент может быть выбран в любое время. Выбранный элемент является конкретным именем таблицы.

Затем, адаптер базы данных, tableAdapter, создается только один раз. Функция onCreate создает все таблицы в базе данных. Посмотрите на фрагмент кода для этого процесса;

1
if (DATABASE_STATUS == «new» ) { String str1 =»»;

Это один из способов реализации алгоритма создания нескольких таблиц. Каждая таблица, имя поля и тип поля собираются в строку SQL. Поле идентификатора «_id» и запрограммировано (не вводится) для каждой таблицы. После сборки строки SQL выполняется db.execSql (str1) и создается таблица SQL. Теоретически, этот метод интерактивного ввода не должен ограничивать количество таблиц или количество полей. Однако DataAttrib устанавливает ограничение размера [10] для одномерного и [10] [10] для двумерных массивов. Его можно увеличить до любого желаемого значения. Кроме того, функция проверки дубликатов требует не менее двух столбцов таблицы в дополнение к полю _id.

Затем выполняется поиск дубликатов в таблице с помощью оператора SQL, который использует первые два поля в критериях поиска. Имена условных полей извлекаются из курсора с помощью запроса PRAGMA для текущей таблицы. Использование запроса PRAGMA облегчает использование нескольких адаптеров базы данных. Курсор базы данных создается с помощью процесса db.rawQuery (…). Типичный SQL-запрос поиска должен быть знаком пользователям базы данных ACCESS следующим образом:

1
2
3
4
5
String chkVar =»( » + xtbl + «.» + colName[1] +»||’ ‘||»+ xtbl + «.» + colName[2]+» )»;
String sql = «SELECT » +
                  chkVar + » AS Var1, » +
       » count» + chkVar + » » + » as NumDupes» +
       » FROM » + xtbl +» Group by » + chkVar + » having ((count» + chkVar + «)>1);»;

где xtbl — текущая выбранная таблица. Если дубликаты найдены, пользователь получает оповещения с помощью оповещений Toast, и результаты печатаются в представлении «Прокрутка» под блоком редактирования с пометкой «запрос». Дубликаты данных не удаляются автоматически. Это можно сделать более эффективно, используя Run Query и интерфейс CRUD.

Затем устанавливаются все компоненты представления и определяются функции обратного вызова для прослушивателей кнопок.

Есть много способов ввода данных в таблицу. Здесь мы используем четыре поля ввода EditBox (F1, Fld2, Fld3 и Fld 4) для обработки данных. F1 зарезервирован для поля _id, и пользователь взаимодействует с ним только при удалении или обновлении таблицы. Другие поля предназначены для имен полей, таких как fname и lname, в таблице Players. Если у вас более трех входов, вы можете использовать поле Query для выполнения любой операции CRUD. Давайте введем «Bobby» в Fld2 и «Fisher» в Fld3 («Никогда не ставьте», поскольку они используются здесь только для пояснения). Нажмите кнопку «Создать». Это сохранит данные в таблице базы данных. Вы можете ввести столько данных, сколько вы желание. Давайте рассмотрим эту схему вставки данных чуть подробнее. Ниже приведен фрагмент кода.

1
private void createData() { try { String xtbl = input.getText().toString();

Это типичная схема ввода данных. Как обычно, есть много других возможных способов сделать вставку данных в таблицу. Здесь xtbl — данные, выбранные в элементе управления счетчиком. Имена полей взяты из переменной x [] из входных данных. Мы вызываем PRAGMA, чтобы получить имена полей этой конкретной таблицы как colName []. Мы используем класс ContentValues, чтобы назначить входные данные соответствующим именам столбцов. Наконец, db1.insert (…) вставляет входные данные в базу данных.

Другие операции CRUD, а именно чтение, обновление и удаление, следуют аналогичной логике с соответствующими операторами SQL.

Кнопка Read требует ввода номера _id. Поместите номер _id в поле F1 и нажмите эту кнопку, чтобы данные отображались в других полях.

Кнопка Обновить также работает с вводом _id. Сначала получите правильные данные с помощью операции чтения, затем внесите изменения в другие поля ввода. Нажмите кнопку Обновить, чтобы сохранить изменения.

Кнопка Удалить также работает с полем _id. Введите номер _id и нажмите кнопку Удалить. Данные будут удалены без предупреждения, если не будут нарушены некоторые ограничения внешнего ключа.

Строки кнопок first, rev, next, last и search используются для навигации по данным в таблице. Сначала вставьте в таблицу столько записей, сколько хотите. С помощью этих кнопок вы можете просматривать свои входные данные. Если у вас много записей, найти запись будет очень сложно. Для этого удобна кнопка поиска. Все поиски выполняются по комбинации первых двух полей, введенных в Fld2 и Fld3. Поиск требует частичного ввода и нечувствителен к регистру.

При навигации по базе данных используются имена полей из PRAGMA и соответствующий db.query для извлечения всех данных таблицы в курсоре. Навигация осуществляется с помощью функций cursor.moveToFirst (), cursor.moveToLast (), cursor.setPosition (), курсора, getPosition, cursor.moveToPrevious () и cursor.moveToNext ().

Операции поиска используют опцию LIKE. Сообщалось, что этот тип критериев замедляет поиск на больших таблицах. На сайте Android Developer есть альтернативный метод быстрого поиска. Чтобы сделать процесс поиска нечувствительным к регистру и принимать частичные входные данные, используется следующее условие для функции searchData ().

1
2
String str2 = «lower(» + y[1] + «)» + » like «+ «lower(«+ «‘%»+xsearch[0].trim()+»%'»+ «)» +» and » +
                      «lower(» + y[2] + «)» + » like «+ «lower(«+ «‘%»+xsearch[1].trim()+»%'»+ «)»;

где y [] — имя поля, а xsearch [] — строка поиска. Это очень полезная схема. Многие другие эффективные алгоритмы поиска также используются при поиске в базе данных. Индекс также генерируется в двух полях поиска, чтобы ускорить процесс двоичного поиска.

Далее, Run Query — довольно полезный инструмент для запуска запросов. Когда вы нажимаете кнопку Run Query, появляется всплывающее диалоговое окно. Этот подход хорошо работает для ввода длинных запросов из-за ограниченной области отображения на эмуляторе. Введите запрос, который возвращает некоторые данные, например «Select * from any_table;» и нажмите кнопку Go. Возвращенные данные будут отображаться в поле прокрутки под кнопкой «Выполнить запрос». Запросы можно запускать для любой таблицы, независимо от выбранной в данный момент в элементе управления Spinner. С этим параметром вы можете делать все, что захотите, с базой данных. Выйдите из экрана Query Input, нажав кнопку Exit.

Кнопка «Назад» возвращает вас к операции ввода данных. Вы можете только перезапустить активные базы данных отсюда. Для новых вам придется выйти и снова войти в приложение.

Одним из очень полезных операторов SQL для эффективного программирования является PRAGMA, который имеет следующую структуру:

PRAGMA table_info (имя_таблицы);

Это генерирует пять столбцов вывода. Второй столбец — это имя переменной поля, а третий — тип поля.

Вы можете изменить выбор таблиц и управлять своей базой данных по своему усмотрению. Все эти операции для всех таблиц выполняются только с одним классом адаптера базы данных.

Когда выбрана существующая база данных, имя и версия базы данных передаются из входного графического интерфейса в графический интерфейс навигации. База данных подключается в функции адаптера onCreate, предоставляя путь к существующей базе данных. Убедитесь, что вы изменили имя пакета в пути к вашему местоположению. Имена таблиц извлекаются с использованием следующего SQL:

1
2
3
4
«SELECT name FROM «+ » sqlite_master WHERE type=’table’ » +
          » AND name NOT LIKE ‘sqlite_%’ AND name NOT LIKE ‘android%’ UNION ALL» +
          » SELECT name FROM sqlite_temp_master WHERE type=’table’ » +
          » ORDER BY 1;»;

где ‘table’ — внутренняя переменная базы данных схемы. В остальном управление базой данных такое же, как в новом случае базы данных.

База данных ввода Query имеет ряд символьных ограничений из EditBox. Критический тест управления запросами Run сопровождается следующим sql в указанной статье;

01
02
03
04
05
06
07
08
09
10
sql = «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;»;

Это Java-версия SQL. Чтобы поместить в поле «Запрос», вы должны избавиться от знаков «и +». Используйте тот, который указан в указанной статье. Даже этот длинный запрос можно запустить с помощью всплывающего запроса. Убедитесь, что запрос введен правильно, в противном случае может произойти сбой или ничего не произойдет.

Кнопка Quit выходит из этого приложения. Если вы создали новые таблицы, индексы и триггеры, вам придется выйти из текущей настройки и повторно войти, чтобы увидеть новые вещи.

Возможно, вы заметили, что адаптер базы данных был создан только один раз. Использование PRAGMA и продуманное программирование избавляет от необходимости использования нескольких громоздких адаптеров. Некоторые из вас могут использовать подобные схемы в своей повседневной работе, но для остальных из нас это должна быть новая и эффективная схема!