Как подключить SQL server к android studio?
Как к Visual Studio подключить базу MS SQL Server?
Может кто подсказать как к Visual Studio подключить базу MS SQL Server?
Как подключить MS SQL Server 2008 R2 к Visual Studio 2010
Подскажите, пожалуйста как подключить MS SQL Server 2008 R2 к Visual Studio 2010. У меня на.

Android Studio + Sql server
Здравствуйте, была создана информационная система(клиентское приложение для windows) на языке c#.
Как в Android studio подключить ffmpeg
Как подключить библиотеку ffmpeg в Android studio?? Я видел только в эклипс а в студию как.
Регистрация: 20.02.2016
Сообщений: 11
ВОТ КОД САМОЙ ПРОГРАММЫ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
package com.example.ls.connection_ms_sql; import android.os.Bundle; import android.view.View; import android.app.Activity; import android.util.Log; import android.widget.Button; import android.widget.TextView; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class MainActivity extends Activity { TextView textView1; Button button; final String LOG_TAG = "myLogs"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textView1 = (TextView) findViewById(R.id.textView1); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { Connection connection = null; String url = "jdbc:jtds:sqlserver://SERVERNAME:1434/test123"; String name = "name"; String password = "pass"; try { connection = DriverManager.getConnection(url, name, password); Log.d(LOG_TAG, "я подключился"); } catch (SQLException e) { e.printStackTrace(); Log.d(LOG_TAG, "а ты что думал, что с первого раза все получится. "); } } catch (Exception e) { e.printStackTrace(); } } }); try { Class.forName("net.sourceforge.jtds.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Добавлено через 2 минуты
И вот что он мне выдает на выходе:
Кликните здесь для просмотра всего текста
03-02 09:41:04.257 26014-26014/com.example.ls.connection_ms_sql I/View: Touch down dispatch to android.widget.Button<1c1f1919 VFED..C. . 224,1102-496,1198 #7f0c006c app:id/button>, event = MotionEvent < action=ACTION_DOWN, id[0]=0, x[0]=162.46326, y[0]=68.046875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=586635241, downTime=586635241, deviceId=7, source=0x1002 >
03-02 09:41:04.298 26014-26014/com.example.ls.connection_ms_sql I/View: Touch up dispatch to android.widget.Button<1c1f1919 VFED..C. . p. 224,1102-496,1198 #7f0c006c app:id/button>, event = MotionEvent < action=ACTION_UP, id[0]=0, x[0]=162.46326, y[0]=68.046875, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=586635295, downTime=586635241, deviceId=7, source=0x1002 >
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: java.sql.SQLException: No suitable driver
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at java.sql.DriverManager.getConnection(DriverManager.java:186)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at java.sql.DriverManager.getConnection(DriverManager.java:213)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at com.example.ls.connection_ms_sql.MainActivity$1.onClick(MainActivity.java:38)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.view.View.performClick(View.java:4770)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.view.View$PerformClick.run(View.java:19801)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.os.Looper.loop(Looper.java:135)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5261)
03-02 09:41:04.320 26014-26014/com.example.ls.connection_ms_sql W/System.err: at java.lang.reflect.Method.invoke(Native Method)
03-02 09:41:04.321 26014-26014/com.example.ls.connection_ms_sql W/System.err: at java.lang.reflect.Method.invoke(Method.java:372)
03-02 09:41:04.321 26014-26014/com.example.ls.connection_ms_sql W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:939)
03-02 09:41:04.321 26014-26014/com.example.ls.connection_ms_sql W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:734)
03-02 09:41:04.321 26014-26014/com.example.ls.connection_ms_sql D/myLogs: а ты что думал, что с первого раза все получится.1c1f1919>
Добавлено через 1 минуту
Спасайте.
Android. Работаем с MS SQL без посредников

Предупреждение:
Вообще говоря, информация из статьи применима только для некоторых специфических случаев. Например, когда приложение работает внутри какого-то сегмента изолированной сети. А в общем случае посредник, коим является http-сервер, всё-таки нужен. Хотя бы потому, что при описанном методе логин/пароль доступа к базе зашиты в приложении и передаются по сети.
Статья является продолжением работы, о которой писал в своём предыдущем посте. Изначально эту часть писать не хотелось (см. предупреждение), но на хабре данная тема ещё не освещена, и в целом в сети меньше информации.
Поэтому, если Вам интересно, как можно из под Android напрямую работать с MS SQL (логично предположить, что и с другими БД, но на практике я этого не делал), добро пожаловать под кат.
В Java (и Android соответственно) соединение с удалёнными БД происходит при помощи JDBC-драйверов. В моём конкретном случае сервер майкрософтовский, и для него существует два драйвера: от Microsoft и открытая альтернатива JTDS. Причём последний, по заверениям разработчиков, работает быстрее и стабильней официального. Вот его и будем использовать.
Грабли: Актуальная версия JTDS на дату написания поста — 1.3.1. Но начиная с версии 1.3.0 драйвер переписан для совместимости с Java 7, и в сети встречаются сообщения о проблеме работы этих версий в Android. Поэтому необходимо использовать последнюю стабильную версию ветки 1.2.* (1.2.8), которая для Java 6.
На SQL-сервере должна быть настроена работа через TCP/IP.
Получение данных
Данные запросов драйвер возвращает в интерфейсе ResultSet который похож на андроидный Cursor, но быстрого способа приведения ResultSet к курсору я не нашёл. Поэтому поступим по-другому, данные из ResultSet будут конвертироваться в массив JSONArray и возвращаться в основную логику приложения, откуда с ними можно будет делать что угодно.
Весь обмен данными, как потенциально продолжительную операцию, будем делать асинхронно. В итоге получается примерно такой симпатичный класс для запросов к MS SQL:
EDIT: Переписал закрытие Connection, Statement и ResultSet в примерах в соответствии с основами.
public final class AsyncRequest extends AsyncTask < final static String MSSQL_DB final static String MSSQL_LOGIN ; final static String MSSQL_PASS ; @Override protected JSONArray doInBackground(String. query) < JSONArray resultSet = new JSONArray(); try < Class.forName("net.sourceforge.jtds.jdbc.Driver"); Connection con = null; Statement st = null; ResultSet rs = null; try < con = DriverManager.getConnection(MSSQL_DB, MSSQL_LOGIN, MSSQL_PASS); if (con != null) < st = con.createStatement(); rs = st.executeQuery(query[0]); if (rs != null) < int columnCount = rs.getMetaData().getColumnCount(); // Сохранение данных в JSONArray while (rs.next()) < JSONObject rowObject = new JSONObject(); for (int i = 1; i resultSet.put(rowObject); > > > > catch (SQLException e) < e.printStackTrace(); >catch (JSONException e) < e.printStackTrace(); >finally < try < if (rs != null) rs.close(); if (st != null) st.close(); if (con != null) con.close(); >catch (SQLException e) < throw new RuntimeException(e.getMessage()); >> > catch (ClassNotFoundException e) < e.printStackTrace(); >return resultSet; > @Override protected void onPostExecute(JSONArray result) < // TODO: вернуть результат >>
На вход классу подаётся запрос, на выходе — готовый JSONArray, как если бы мы получали данные от веб-сервера. В отдельном потоке AsyncTask соединяется с сервером, получает данные в ResultSet и формирует из них JSON. Думаю, в целом код примитивен и в пояснениях не нуждается.
Для построения систем, работающих по подобному принципу, лучше передавать на вход не чистые select-запросы, а написать на сервере готовые T-SQL функции, передавая параметры к которым, можно получать нужные выборки.
Insert и Update. Передача данных на сервер
К сожалению, тут я не придумал ничего лучше, просто выполнение Insert-ов в транзакции. В прочем, метод отлично работает, вставка нескольких сотен записей занимает приемлемое время (около секунды на 100 строк, полей в реальном проекте больше, чем в приведённом примере).
EDIT: по совету eyeless_watcher использую метод addBatch() при заполнении PreparedStatement. Вот теперь вставка данных выполняется на самом деле быстро, в одной транзакции. Пример изменил.
public final class AsyncInsert extends AsyncTask < private static final String REMOTE_TABLE = "dbo.TableName"; private static final String SQL = "INSERT into " + REMOTE_TABLE + "([" + ListItemScanned.BARCODE + "],[" + ListItemScanned.NR_ID + "],[" + ListItemScanned.DATE + "],[" + ListItemScanned.STATUS + "]) values(. )"; private final ListmData; public AsyncInsert(List data) < this.mData = data; >@Override protected JSONArray doInBackground(String. proc_params) < JSONArray resultSet = new JSONArray(); try < Class.forName("net.sourceforge.jtds.jdbc.Driver"); Connection con = null; PreparedStatement prepared = null; try < con = DriverManager.getConnection(MSSQL_DB, MSSQL_LOGIN, MSSQL_PASS); if (con != null) < prepared = con.prepareStatement(SQL); for (ListItemScanned item : mData) < prepared.setString(1, item.get(ListItemScanned.BARCODE)); prepared.setString(2, item.get(ListItemScanned.NR_ID)); prepared.setString(3, item.get(ListItemScanned.DATE)); prepared.setString(4, item.get(ListItemScanned.STATUS)); prepared.addBatch(); resultSet.put(item.get(ListItemScanned.ID)); >prepared.executeUpdate(); return resultSet; > > catch (SQLException e) < e.printStackTrace(); >finally < try < if (prepared != null) prepared.close(); if (con != null) con.close(); >catch (SQLException e) < throw new RuntimeException(e.getMessage()); >> > catch (ClassNotFoundException e) < e.printStackTrace(); >return resultSet; >
Для вставки нужных значений используется PreparedStatement. Нумерация полей в нём почему-то начинается с единицы (см. документацию). А в остальном — всё должно быть понятно. update можно реализовать схожим образом, аналогично используя executeUpdate.
Приведённый подход был использован мной в «боевом» приложении первый раз.
На практике оказалось, что он стабильно работает. Время соединения с БД иногда может занимать несколько секунд (подключаюсь по wi-fi, сервер общий на всё предприятие), но сами транзакции выполняются быстро.
Дополнения и критика — приветствуются 🙂
Сохранение данных в SQL базу данных
Сохранение данных в базу данных идеально подходит для повторяющихся или структурированных данных, такие как контактная информация. Этот курс предполагает, что вы знакомы с SQL базами данных в целом, и это поможет вам начать работу с SQLite базами данных на Android. API интерфейсы, которые вы будете использовать для работы с базой данных на Android доступны в android.database.sqlite пакете.
Определить схемы и контракты
Одним из основных принципов SQL баз данных является схема: формальное описание того, как база данных организована. Схема отражена в SQL запросах, которые вы используете для создания базы данных. Возможно, вам будет полезно создать класс компаньон, известный как контракт , который явно определяет макет вашей схемы систематическим и самодокументируемым образом.
Контрактный класс представляет собой контейнер для констант, определяющих имена для URI, таблиц и столбцов. Класс контракта позволяет использовать одни и те же константы во всех других классах в том же пакете. Это позволяет изменить имя столбца в одном месте и распространить изменение по всему коду.
Хороший способ организовать класс контракта это разместить определения, которые являются глобальными для всей базы данных, в корневом уровне класса. Затем создайте внутренние классы для каждой из таблиц, которые перечисляют свои столбцы.
Примечание: Реализуя BaseColumns интерфейс, ваш внутренний класс может унаследовать поле первичного ключа, называемое _ID , наличие которых будут ожидать некоторые Android классы, такие как курсоры адаптеров. Это не обязательно, но это может помочь вашей работе с базой данных в гармонии с библиотеками Android.
Например, этот фрагмент определяет имя таблицы и имена столбцов для одной из таблиц:
public final class FeedReaderContract < // To prevent someone from accidentally instantiating the contract class, // give it an empty constructor. public FeedReaderContract() <>/* Inner class that defines the table contents */ public static abstract class FeedEntry implements BaseColumns < public static final String TABLE_NAME = "entry"; public static final String COLUMN_NAME_ENTRY_ID = "entryid"; public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_SUBTITLE = "subtitle"; . >>
Создание базы данных с помощью SQL помощника
После того как вы определили, как выглядит ваша база данных, вы должны реализовать методы, которые создают и поддерживают базу данных и таблицы. Вот некоторые типичные запросы, которые создают и удалять таблицы:
private static final String TEXT_TYPE = " TEXT"; private static final String COMMA_SEP = ","; private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + FeedEntry._ID + " INTEGER PRIMARY KEY," + FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP + FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP + . // Any other options for the CREATE command " )"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
Так же, как файлы, которые вы храните на устройстве во внутреннем хранилище, Android хранит вашу базу данных в приватной части дискового пространства, ассоциированном с приложением. Ваши данные надежно защищены, потому что по умолчанию эта область не является доступной для других приложений.
Полезный набор функций API доступен в SQLiteOpenHelper классе. Когда вы используете данный класс для получения ссылки на базу данных, система выполняет потенциально длительные операции создания и обновления базы данных только при необходимости и не во время запуска приложения. Все что вам нужно сделать это вызвать getWritableDatabase() или getReadableDatabase() .
Примечание: Т.к. они могут быть длительными, убедитесь, что вы вызываете getWritableDatabase() или getReadableDatabase() в фоновом потоке, например, используя AsyncTask или IntentService .
Чтобы использовать SQLiteOpenHelper , создайте подкласс, который перегружает onCreate() , onUpgrade() и onOpen() методы обратного вызова. Вы также можете реализовать onDowngrade() , но это не обязательно.
Например, вот реализация SQLiteOpenHelper , который использует некоторые из команд, показанных выше:
public class FeedReaderDbHelper extends SQLiteOpenHelper < // If you change the database schema, you must increment the database version. public static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "FeedReader.db"; public FeedReaderDbHelper(Context context) < super(context, DATABASE_NAME, null, DATABASE_VERSION); >public void onCreate(SQLiteDatabase db) < db.execSQL(SQL_CREATE_ENTRIES); >public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) < // This database is only a cache for online data, so its upgrade policy is // to simply to discard the data and start over db.execSQL(SQL_DELETE_ENTRIES); onCreate(db); >public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) < onUpgrade(db, oldVersion, newVersion); >>
Для доступа к базе данных, создайте экземпляр подкласса SQLiteOpenHelper :
FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());
Положить информацию в базу данных
Вставьте данные в базу данных, передав ContentValues объект в insert() метод:
// Gets the data repository in write mode SQLiteDatabase db = mDbHelper.getWritableDatabase(); // Create a new map of values, where column names are the keys ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id); values.put(FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedEntry.COLUMN_NAME_CONTENT, content); // Insert the new row, returning the primary key value of the new row long newRowId; newRowId = db.insert( FeedEntry.TABLE_NAME, FeedEntry.COLUMN_NAME_NULLABLE, values);
Первый аргумент для insert() это просто имя таблицы. Второй аргумент содержит имя столбца, в который библиотека может вставить значение NULL в случае, если ContentValues пуст (если вы вместо этого установите его «null» , то библиотека не сможет вставить строку, когда нет ни одного значения).
Считать информацию из базы данных
Для чтения из базы данных, используйте query() метод, передавая ему свои критерии отбора и нужные столбцы. Метод сочетает в себе элементы insert() и update() , но список столбцов определяет данные, которые вы хотите получить, а не вставить. Результаты запроса возвращаются в Cursor объекте.
SQLiteDatabase db = mDbHelper.getReadableDatabase(); // Define a projection that specifies which columns from the database // you will actually use after this query. String[] projection = < FeedEntry._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_UPDATED, . >; // How you want the results sorted in the resulting Cursor String sortOrder = FeedEntry.COLUMN_NAME_UPDATED + " DESC"; Cursor c = db.query( FeedEntry.TABLE_NAME, // The table to query projection, // The columns to return selection, // The columns for the WHERE clause selectionArgs, // The values for the WHERE clause null, // don't group the rows null, // don't filter by row groups sortOrder // The sort order );
Чтобы посмотреть на значения строки данных в курсоре, используйте один из методов перемещения Cursor , которые вы всегда должны вызывать, прежде чем начать вычитывать значения. Как правило, вы должны начать с вызова moveToFirst() , которая ставит “позицию чтения” на первую запись результата. Для каждой строки, вы можете прочитать значение столбца вызвав один из методов Cursor для получения значений, таких как getString() или getLong() . Для каждого из методов получения, вы должны передать индекс желаемой позиции столбца, который вы можете получить, вызвав getColumnIndex() или getColumnIndexOrThrow() . Например:
cursor.moveToFirst(); long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedEntry._ID) );
Удаление информации из базы данных
Для удаления строки из таблицы, необходимо предоставить критерии отбора, которые идентифицируют строки. API базы данных предоставляет механизм для создания критериев отбора, который защищает от SQL инъекций. Механизм разделяет спецификацию отбора на запрос отбора и его аргументы. Запрос определяет столбцы, по которым будут отбираться записи, а также позволяет задать значения для проверки по полям. Значения аргументов для проверки связаны с запросом. Т.к. результат не обрабатываются так же, как обычный SQL запрос, это защищает от SQL инъекций.
// Define 'where' part of query. String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; // Specify arguments in placeholder order. String[] selectionArgs = < String.valueOf(rowId) >; // Issue SQL statement. db.delete(table_name, selection, selectionArgs);
Обновление базы данных
Когда вам необходимо изменить подмножество значений в базе данных, используйте update() метод.
Обновление значений таблицы сочетает в себе синтаксис insert() с where синтаксисом delete() .
SQLiteDatabase db = mDbHelper.getReadableDatabase(); // New value for one column ContentValues values = new ContentValues(); values.put(FeedEntry.COLUMN_NAME_TITLE, title); // Which row to update, based on the ID String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; String[] selectionArgs = < String.valueOf(rowId) >; int count = db.update( FeedReaderDbHelper.FeedEntry.TABLE_NAME, values, selection, selectionArgs);
Следующий курс: Взаимодействие с другими приложениями
Если не указано иное, этот контент распространяется под лицензией Creative Commons Attribution 2.5. Для получения дополнительной информации и ограничений, см. Лицензия контента.
Использование простой базы данных SQLite в Android-приложении
В этом руководстве я подробно расскажу о том, как использовать базу данных Android SQLite .
Что такое SQLite
SQLite — это система управления реляционными базами данных, похожая на Oracle , MySQL , PostgreSQL и SQL Server . Она реализует большую часть стандарта SQL , но в отличие от четырех упомянутых выше СУБД она не поддерживает модель « клиент-сервер ». Скорее, она встроена в конечную программу. Это означает, что можно связать базу данных SQLite с приложением и получить доступ ко всем возможностям БД в своем приложении.

Данная СУБД совместима как с Android , так и с iOS , и каждое приложение может создавать и использовать базу данных SQLite . В Android контакты и медиа хранятся и ссылаются на БД SQLite . Она является наиболее используемой СУБД в мире и самым распространенным программным обеспечением. Чтобы узнать о базах данных SQLite как можно больше, посетите официальный сайт SQLite.
Подготовка
Чтобы включить привязку данных в приложении, нужно добавить в файл build.gradle следующий код:
dataBinding.enabled = true
Чтобы использовать как RecyclerView , так и CardView для отображения списков, нужно включить соответствующие библиотеки в разделе зависимостей в файле build.gradle :
dependencies
Чтобы задействовать все возможности базы данных 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 :
public final class SampleDBContract < private SampleDBContract() < >public static class Employer implements BaseColumns < public static final String TABLE_NAME = "employer"; public static final String COLUMN_NAME = "name"; public static final String COLUMN_DESCRIPTION = "description"; public static final String COLUMN_FOUNDED_DATE = "date"; public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_NAME + " TEXT, " + COLUMN_DESCRIPTION + " TEXT, " + COLUMN_FOUNDED_DATE + " INTEGER" + ")"; >>
Мы определяем частный конструктор для SampleDBContract , а затем создаем класс для представления таблицы Employer . Обратите внимание: класс Employer реализует интерфейс BaseColumns . Он предоставляет два столбца в нашей таблице. Это столбец _ID , который будет автоматически увеличиваться при добавлении каждой новой строки. И столбец _COUNT , который может использоваться ContentProviders для возврата количества записей, извлекаемых через запрос. Столбец _COUNT не является обязательным. Строка CREATE_TABLE компилируется в следующий оператор SQL :
CREATE TABLE IF NOT EXISTS employer (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, date INTEGER)
На данный момент в нашем Android SQLite примере мы определили схему таблицы Employer .
Создание базы данных с помощью SQLiteOpenHelper
Самый простой способ управления созданием базы данных и версиями — создать подкласс SQLiteOpenHelper . Он упрощает управление базой данных SQLite , создавая БД, если они не существуют. Необходимо только переопределить методы onCreate() и onUpgrade() , чтобы указать нужное действие для создания или обновления базы данных:
public class SampleDBSQLiteHelper extends SQLiteOpenHelper < private static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "sample_database"; public SampleDBSQLiteHelper(Context context) < super(context, DATABASE_NAME, null, DATABASE_VERSION); >@Override public void onCreate(SQLiteDatabase sqLiteDatabase) < sqLiteDatabase.execSQL(SampleDBContract.Employer.CREATE_TABLE); >@Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employer.TABLE_NAME); onCreate(sqLiteDatabase); >>
Теперь в нашем примере 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 , который открывает доступ на чтение / запись:
private void saveToDB() < SQLiteDatabase database = new SampleDBSQLiteHelper(this).getWritableDatabase(); ContentValues values = new ContentValues(); values.put(SampleDBContract.Employer.COLUMN_NAME, binding.nameEditText.getText().toString()); values.put(SampleDBContract.Employer.COLUMN_DESCRIPTION, binding.descEditText.getText().toString()); try < Calendar calendar = Calendar.getInstance(); calendar.setTime((new SimpleDateFormat("dd/MM/yyyy")).parse( binding.foundedEditText.getText().toString())); long date = calendar.getTimeInMillis(); values.put(SampleDBContract.Employer.COLUMN_FOUNDED_DATE, date); >catch (Exception e) < Log.e(TAG, "Error", e); Toast.makeText(this, "Date is in the wrong format", Toast.LENGTH_LONG).show(); return; >long newRowId = database.insert(SampleDBContract.Employer.TABLE_NAME, null, values); Toast.makeText(this, "The new Row Id is " + newRowId, Toast.LENGTH_LONG).show(); >
В приведенном выше фрагменте кода есть четыре момента:
- Мы получаем объект SQLiteDatabase , который открывает доступ на запись в базу данных;
- Значения, которые будут храниться в базе данных, помещаются в объект ContentValue с именем столбца в качестве ключа;
- Мы помещаем Date в объект ContentValue , который переводится в класс хранения данных Android SQLite INTEGER ;
- При вставке строки в базу данных с помощью метода database.insert() возвращается идентификатор строки.
Выбор данных из базы данных SQLite
Подобно тому, как мы применили метод getWritableDatabase() , можно вызвать getReadableDatabase() объекта SQLiteOpenHelper для получения объекта SQLiteDatabase , который можно использовать для чтения информации из базы данных. Стоит отметить, что объект SQLiteDatabase , возвращаемый getReadableDatabase() , предоставляет собой тот же самый доступ на чтение / запись в базу данных, который был возвращен функцией getWritableDatabase() , за исключением тех случаев, когда существуют определенные ограничения. Например, файловая система, содержащая заполненную базу данных, и база данных может быть открыта только для чтения.
Метод readFromDB будет запрашивать БД, и возвращать все строки из таблицы Employer , в которых имя или описание из таблицы Employer совпадает со значением, введенным в EditText . А также строки, в которых дата основания компании совпадает со значением, введенным в EditText :
private void readFromDB() < String name = binding.nameEditText.getText().toString(); String desc = binding.descEditText.getText().toString(); long date = 0; try < Calendar calendar = Calendar.getInstance(); calendar.setTime((new SimpleDateFormat("dd/MM/yyyy")).parse( binding.foundedEditText.getText().toString())); date = calendar.getTimeInMillis(); >catch (Exception e) <> SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); String[] projection = < SampleDBContract.Employer._ID, SampleDBContract.Employer.COLUMN_NAME, SampleDBContract.Employer.COLUMN_DESCRIPTION, SampleDBContract.Employer.COLUMN_FOUNDED_DATE >; String selection = SampleDBContract.Employer.COLUMN_NAME + " like ? and " + SampleDBContract.Employer.COLUMN_FOUNDED_DATE + " > ? and " + SampleDBContract.Employer.COLUMN_DESCRIPTION + " like ?"; String[] selectionArgs = ; Cursor cursor = database.query( SampleDBContract.Employer.TABLE_NAME, // Запрашиваемая таблица projection, // Возвращаемый столбец selection, // Столбец для условия WHERE selectionArgs, // Значение для условия WHERE null, // не группировать строки null, // не фильтровать по группам строк null // не сортировать ); Log.d(TAG, "The total cursor count is " + cursor.getCount()); binding.recycleView.setAdapter(new SampleRecyclerViewCursorAdapter(this, cursor)); >
В коде 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 :
public class SampleRecyclerViewCursorAdapter extends RecyclerView.Adapter < Context mContext; Cursor mCursor; public SampleRecyclerViewCursorAdapter(Context context, Cursor cursor) < mContext = context; mCursor = cursor; >public static class ViewHolder extends RecyclerView.ViewHolder < EmployerListItemBinding itemBinding; public ViewHolder(View itemView) < super(itemView); itemBinding = DataBindingUtil.bind(itemView); >public void bindCursor(Cursor cursor) < itemBinding.nameLabel.setText(cursor.getString( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_NAME) )); itemBinding.descLabel.setText(cursor.getString( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_DESCRIPTION) )); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(cursor.getLong( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_FOUNDED_DATE))); itemBinding.foundedLabel.setText(new SimpleDateFormat("dd/MM/yyyy").format(calendar.getTime())); >> @Override public int getItemCount() < return mCursor.getCount(); >@Override public void onBindViewHolder(ViewHolder holder, int position) < mCursor.moveToPosition(position); holder.bindCursor(myCursor); >@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) < View view = LayoutInflater.from(parent.getContext()).inflate( R.layout.employer_list_item, parent, false); ViewHolder viewHolder = new ViewHolder(view); return viewHolder; >>

Определение внешних ключей
На данный момент в нашем Android SQLite примере мы создали таблицу Employer , которую заполнили строками. Теперь создадим таблицу Employee , которая связана с таблицей Employer через столбец _ID Employer . Мы определяем класс Employee , который расширяет BaseColumns в классе SampleDBContract . Обратите внимание, что при создании таблицы Employee использовали » FOREIGN KEY(employer_id) REFERENCES employer(_id) «:
public static class Employee implements BaseColumns
Обновление SQLiteOpenHelper
На данный момент в Android Studio SQLite у вас должна быть создана таблица Employer и в нее добавлены значения. Если вы не изменяете версию базы данных, новая таблица Employee не будет создана. К сожалению, если вы измените версию через повторный вызов метода onUpgrade() , то таблица Employer будет сброшена. Чтобы предотвратить это, можно закомментировать или удалить оператор drop в методе onUpgrade() и добавить оператор execSQL() для создания таблицы Employee . Поскольку таблица Employee ссылается на таблицу Employer , сначала необходимо создать таблицу Employer :
public class SampleDBSQLiteHelper extends SQLiteOpenHelper < private static final int DATABASE_VERSION = 2; public static final String DATABASE_NAME = "sample_database"; public SampleDBSQLiteHelper(Context context) < super(context, DATABASE_NAME, null, DATABASE_VERSION); >@Override public void onCreate(SQLiteDatabase sqLiteDatabase) < sqLiteDatabase.execSQL(SampleDBContract.Employer.CREATE_TABLE); sqLiteDatabase.execSQL(SampleDBContract.Employee.CREATE_TABLE); >// Мы не хотим удалять данные пользователей. @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) < if(oldVersion == 0 && newVersion == 2) < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employee.TABLE_NAME); >else < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employer.TABLE_NAME); sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employee.TABLE_NAME); >onCreate(sqLiteDatabase); > >
Отображение данных из запроса SQLite в Spinner
Чтобы создать работника в таблице Employee , пользователю необходимо выбрать соответствующего работодателя в таблице Employer . Для этого можно предоставить пользователю Spinner . Отобразить содержимое Cursor в Spinner довольно просто.
Сначала мы выполняем Android SQLite query , как было описано выше, выбираем только name из Employer и id (queryCols) . Затем создаем экземпляр SimpleCursorAdapter , передавая ему Cursor , массив столбцов для отображения ( adapterCols ) и массив представлений, с помощью которых должны отображаться столбцы ( adapterRowViews ). Затем устанавливаем Spinner Adapter для SimpleCursorAdapter :
String[] queryCols = new String[]; SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); Cursor cursor = database.query( SampleDBContract.Employer.TABLE_NAME, // Запрашиваемая таблица queryCols, // Возвращаемый столбец null, // Столбец для условия WHERE null, // Значение для условия WHERE null, // не группировать строки null, // не фильтровать по группам строк null // не сортировать ); String[] adapterCols = new String[]; int[] adapterRowViews = new int[]; SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter( this, android.R.layout.simple_spinner_item, cursor, adapterCols, adapterRowViews, 0); cursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); binding.employerSpinner.setAdapter(cursorAdapter);

Вставка внешнего ключа в базу данных
Вставка строки, содержащей внешний ключ, полностью идентична вставке строк в таблицу без ограничений по внешнему ключу. Разница заключается в том, что в Android SQLite примере мы получаем ссылку на выбранный объект Cursor из Spinner , а затем — значение столбца _ID Employer :
values.put(SampleDBContract.Employee.COLUMN_EMPLOYER_ID, ((Cursor)binding.employerSpinner.getSelectedItem()).getInt(0));

Выборка данных из базы SQLite с помощью JOIN
Нельзя использовать метод SQLiteDatabase query() для выполнения запроса к нескольким таблицам. Для этого нужно составить собственный SQL-запрос . В приведенном ниже примере запрос определяется в классе SampleDBContract :
public static final String SELECT_EMPLOYEE_WITH_EMPLOYER = "SELECT * " + "FROM " + Employee.TABLE_NAME + " ee INNER JOIN " + Employer.TABLE_NAME + " er " + "ON ee." + Employee.COLUMN_EMPLOYER_ID + " = er." + Employer._ID + " WHERE " + "ee." + Employee.COLUMN_FIRSTNAME + " like ? AND ee." + Employee.COLUMN_LASTNAME + " like ?";
Обратите внимание, что в условии WHERE мы используем символ « ? ». Чтобы не нарушить синтаксис SQL нужно определить selectArgs String [] со значениями, которые будут заменять в предоставленном SQL-запросе символ « ? »:
private void readFromDB() < String firstname = binding.firstnameEditText.getText().toString(); String lastname = binding.lastnameEditText.getText().toString(); SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); String[] selectionArgs = ; Log.d(TAG, SampleDBContract.Employee.QUERY_WITH_EMPLOYER); Cursor cursor = database.rawQuery(SampleDBContract.Employee.QUERY_WITH_EMPLOYER, selectionArgs); Log.d(TAG, "The total cursor count is " + cursor.getCount()); binding.recycleView.setAdapter(new SampleJoinRecyclerViewCursorAdapter(this, cursor)); >

В заключении
Полная версия исходного кода доступна на github для использования и изменения. Базы данных Android SQLite — это мощное средство, доступное для всех мобильных приложений.