Введение в интерфейс SQLite C/C++
Содержание
1. Обзор
Следующие два объекта и восемь методов составляют основные элементы интерфейса SQLite:
sqlite3 → Объект подключения к базе данных. Создается функцией sqlite3_open() и уничтожается функцией sqlite3_close().
sqlite3_stmt → Объект подготовленного запроса. Создается функцией sqlite3_prepare() и уничтожается функцией sqlite3_finalize().
sqlite3_open() → Открытие соединения с новой или существующей базой данных SQLite. Конструктор для объекта sqlite3.
sqlite3_prepare() → Компиляция SQL-текста в байткод, который выполнит запросы или обновления в базе данных. Конструктор для объекта sqlite3_stmt.
sqlite3_bind() → Хранение данных приложения в параметрах исходного SQL-запроса.
sqlite3_step() → Переход к следующей строке результата или завершение работы объекта sqlite3_stmt.
sqlite3_column() → Значения столбцов в текущей строке результата для объекта sqlite3_stmt.
sqlite3_finalize() → Деструктор для объекта sqlite3_stmt.
sqlite3_close() → Деструктор для объекта sqlite3.
sqlite3_exec() → Функция-оболочка, которая выполняет sqlite3_prepare(), sqlite3_step(), sqlite3_column() и sqlite3_finalize() для одной или нескольких SQL-команд.
2. Введение
В SQLite более 225 API. Однако большинство API являются необязательными и очень специализированными и могут быть проигнорированы новичками. Ядро API небольшое, простое и легко изучается. В этой статье кратко описано ядро API.
Отдельный документ «Интерфейс SQLite C/C++» содержит подробные спецификации всех API C/C++ для SQLite. После понимания основных принципов работы SQLite, этот документ следует использовать в качестве справочника. Данная статья предназначена только для ознакомления и не является полным или авторитетным справочником по API SQLite.
3. Основные объекты и интерфейсы
Основная задача движка SQL-баз данных — вычисление SQL-запросов. Для этого разработчик нуждается в двух объектах:
- Объект подключения к базе данных: sqlite3
- Объект подготовленного запроса: sqlite3_stmt
Строго говоря, объект подготовленного запроса не требуется, так как можно использовать удобные интерфейсы-обертки sqlite3_exec или sqlite3_get_table, которые инкапсулируют и скрывают объект подготовленного запроса. Тем не менее, понимание подготовленных запросов необходимо для полного использования SQLite.
Объекты подключения к базе данных и подготовленного запроса управляются небольшим набором процедур интерфейса C/C++, перечисленных ниже.
Обратите внимание, что список процедур выше концептуальный, а не фактический. Многие из этих процедур существуют в нескольких версиях. Например, в списке указана единственная процедура sqlite3_open(), в то время как на самом деле существует три отдельные процедуры, которые достигают того же результата немного по-разному: sqlite3_open(), sqlite3_open16() и sqlite3_open_v2(). Список упоминает sqlite3_column(), но такой процедуры не существует. «sqlite3_column()» в списке — это плейсхолдер для целого семейства процедур, которые извлекают данные столбцов различных типов данных.
Вот краткое описание того, что делают основные интерфейсы:
-
Эта процедура открывает соединение с файлом базы данных SQLite и возвращает объект подключения к базе данных. Это часто первый вызов API SQLite, который делает приложение, и является предпосылкой для большинства других API SQLite. Многие интерфейсы SQLite требуют указателя на объект подключения к базе данных в качестве своего первого параметра и могут рассматриваться как методы объекта подключения к базе данных. Эта процедура является конструктором для объекта подключения к базе данных.
-
Эта процедура преобразует SQL-текст в объект подготовленного запроса и возвращает указатель на этот объект. Этот интерфейс требует указателя на объект подключения к базе данных, созданного в предыдущем вызове sqlite3_open(), и текстовой строки, содержащей SQL-запрос, который требуется подготовить. Данный API фактически не оценивает SQL-запрос. Он просто подготавливает SQL-запрос для оценки.
Представьте каждый SQL-запрос как небольшую компьютерную программу. Цель sqlite3_prepare() заключается в компиляции этой программы в объектный код. Подготовленный запрос — это объектный код. Интерфейс sqlite3_step() затем выполняет объектный код, чтобы получить результат.
Новые приложения должны всегда вызывать sqlite3_prepare_v2() вместо sqlite3_prepare(). Более старая sqlite3_prepare() сохраняется для обратной совместимости. Но sqlite3_prepare_v2() предоставляет гораздо лучший интерфейс.
-
Эта процедура используется для оценки подготовленного запроса, созданного ранее интерфейсом sqlite3_prepare(). Запрос оценивается до момента, пока не станет доступной первая строка результатов. Чтобы перейти ко второй строке результатов, снова вызовите sqlite3_step(). Продолжайте вызывать sqlite3_step(), пока запрос не будет завершен. Запросы, которые не возвращают результаты (например, INSERT, UPDATE или DELETE), выполняются до конца за один вызов sqlite3_step().
-
Эта процедура возвращает один столбец из текущей строки набора результатов для подготовленного запроса, который оценивается с помощью sqlite3_step(). Каждый раз, когда sqlite3_step() останавливается с новой строкой набора результатов, эту процедуру можно вызывать несколько раз, чтобы найти значения всех столбцов в этой строке.
Как отмечалось выше, функции "sqlite3_column()" в API SQLite фактически нет. Вместо этого, то, что здесь называется "sqlite3_column()", представляет собой плейсхолдер для целого семейства функций, возвращающих значение из набора результатов в различных типах данных. В это семейство также входят процедуры, возвращающие размер результата (если это строка или BLOB) и количество столбцов в наборе результатов.
-
Эта процедура уничтожает подготовленный запрос, созданный ранее вызовом sqlite3_prepare(). Каждый подготовленный запрос должен быть уничтожен с помощью вызова этой процедуры, чтобы избежать утечек памяти.
-
Эта процедура закрывает подключение к базе данных, ранее открытое с помощью вызова sqlite3_open(). Все подготовленные запросы, связанные с подключением, должны быть завершены до закрытия подключения.
4. Типовое использование основных процедур и объектов
Приложение обычно использует sqlite3_open() для создания одного объекта подключения к базе данных во время инициализации. Обратите внимание, что sqlite3_open() может использоваться для открытия существующих файлов базы данных или для создания и открытия новых файлов базы данных. Хотя многие приложения используют только одно подключение к базе данных, нет причин, по которым приложение не может вызывать sqlite3_open() несколько раз, чтобы открыть несколько подключений к базе данных — как к одной и той же, так и к различным базам данных. Иногда многопоточное приложение создаст отдельные подключения к базе данных для каждого потока. Обратите внимание, что одно подключение к базе данных может получить доступ к двум или более базам данных с помощью SQL-команды ATTACH, поэтому нет необходимости иметь отдельное подключение к базе данных для каждого файла базы данных.
Многие приложения уничтожают свои соединения с базой данных с помощью вызовов sqlite3_close() при завершении работы. Например, приложение, использующее SQLite в качестве своего формата файла приложения, может открывать соединения с базой данных в ответ на действие меню «Файл/Открыть» и затем уничтожать соответствующее соединение с базой данных в ответ на действие меню «Файл/Закрыть».
Для выполнения оператора SQL приложение выполняет следующие шаги:
- Создать подготовленное утверждение с помощью sqlite3_prepare().
- Оценить подготовленное утверждение, вызвав sqlite3_step() один или несколько раз.
- Для запросов извлечь результаты, вызвав sqlite3_column() между двумя вызовами sqlite3_step().
- Уничтожить подготовленное утверждение с помощью sqlite3_finalize().
Все вышесказанное — это всё, что действительно нужно знать для эффективного использования SQLite. Всё остальное — это оптимизация и детали.
5. Обёртки для удобства работы с основными процедурами
Интерфейс sqlite3_exec() является обёрткой для удобства, которая выполняет все четыре вышеуказанных шага с помощью одного вызова функции. Функция обратного вызова, передаваемая в sqlite3_exec(), используется для обработки каждой строки набора результатов. sqlite3_get_table() — это ещё одна обёртка для удобства, которая выполняет все четыре вышеуказанных шага. Интерфейс sqlite3_get_table() отличается от sqlite3_exec() тем, что он хранит результаты запросов в памяти кучи, а не вызывает функцию обратного вызова.
Важно понимать, что ни sqlite3_exec(), ни sqlite3_get_table() не делают ничего, что не может быть выполнено с помощью основных процедур. На самом деле, эти обёртки реализованы исключительно с использованием основных процедур.
6. Привязка параметров и повторное использование подготовленных утверждений
В предыдущем обсуждении предполагалось, что каждый оператор SQL подготавливается один раз, оценивается и затем уничтожается. Однако SQLite позволяет использовать одно и то же подготовленное утверждение для оценки несколько раз. Это достигается с помощью следующих процедур:
После того, как подготовленное утверждение было оценено одним или несколькими вызовами sqlite3_step(), его можно сбросить, чтобы его снова оценить, вызвав sqlite3_reset(). Представьте себе sqlite3_reset() как перемотку программы подготовленного утверждения к началу. Использование sqlite3_reset() для существующего подготовленного утверждения вместо создания нового подготовленного утверждения позволяет избежать ненужных вызовов sqlite3_prepare(). Для многих операторов SQL время, необходимое для выполнения sqlite3_prepare(), равно или превышает время, необходимое для выполнения sqlite3_step(). Таким образом, избежание вызовов sqlite3_prepare() может обеспечить значительное улучшение производительности.
Нередко бывает полезно оценивать один и тот же оператор SQL более одного раза. Чаще всего требуется оценивать похожие операторы. Например, вы можете захотеть оценить оператор INSERT несколько раз с разными значениями. Или вы можете захотеть оценить тот же запрос несколько раз, используя другой ключ в условии WHERE. Для этого SQLite позволяет операторам SQL содержать параметры, которые «привязываются» к значениям перед оценкой. Эти значения позже могут быть изменены, и то же подготовленное утверждение может быть оценено во второй раз с использованием новых значений.
SQLite позволяет использовать параметр там, где допускается строковый литерал, литерал BLOB, числовая константа или NULL в запросах или операторах изменения данных. (DQL или DML) (Параметры нельзя использовать для имён столбцов или таблиц или в качестве значений для ограничений или значений по умолчанию. (DDL)) Параметр имеет один из следующих форматов:
- ?
- ?NNN
- :AAA
- $AAA
- @AAA
В приведённых выше примерах NNN — целое значение, а AAA — идентификатор. Изначально параметр имеет значение NULL. Перед вызовом sqlite3_step() в первый раз или сразу после sqlite3_reset() приложение может вызвать интерфейсы sqlite3_bind() для привязки значений к параметрам. Каждый вызов sqlite3_bind() перезаписывает предыдущие привязки к тому же параметру.
Приложению разрешено подготавливать несколько операторов SQL заранее и оценивать их по мере необходимости. Нет произвочного ограничения на количество подготовленных утверждений. Некоторые приложения вызывают sqlite3_prepare() несколько раз при запуске, чтобы создать все подготовленные утверждения, которые им когда-либо понадобятся. Другие приложения хранят кэш наиболее часто используемых подготовленных утверждений и затем повторно используют подготовленные утверждения из кэша, когда они доступны. Ещё один подход — повторно использовать подготовленные утверждения только тогда, когда они находятся внутри цикла.
7. Настройка SQLite
По умолчанию настройка SQLite отлично работает для большинства приложений. Но иногда разработчики хотят настроить параметры, чтобы немного улучшить производительность или воспользоваться какой-нибудь скрытой функцией.
Для внесения глобальных изменений конфигурации SQLite используется интерфейс sqlite3_config(). Интерфейс sqlite3_config() должен быть вызван до создания любых соединений с базой данных. Интерфейс sqlite3_config() позволяет программисту выполнять следующие действия:
- Настроить, как SQLite выполняет выделение памяти, включая настройку альтернативных механизмов выделения памяти, подходящих для критически важных систем реального времени и систем встраивания, а также приложение-определяемых механизмов выделения памяти.
- Настроить процесс-широкий журнал ошибок.
- Указать приложение-определяемый кэш страниц.
- Настроить использование мьютексов таким образом, чтобы они соответствовали различным моделям многопоточности, или заменить их приложение-определяемой системой мьютексов.
После завершения настройки на уровне всего процесса и создания соединений с базой данных, отдельные соединения с базой данных могут быть настроены с помощью вызовов sqlite3_limit() и sqlite3_db_config().
8. Расширение SQLite
SQLite включает интерфейсы, которые можно использовать для расширения его функциональности. К таким процедурам относятся:
Интерфейс sqlite3_create_collation() используется для создания новых последовательностей сортировки для сортировки текста. Интерфейс sqlite3_create_module() используется для регистрации новых реализаций виртуальных таблиц. Интерфейс sqlite3_vfs_register() создаёт новые VFS.
Интерфейс sqlite3_create_function() создаёт новые функции SQL — скалярные или агрегированные. Реализация новой функции, как правило, использует следующие дополнительные интерфейсы:
Все встроенные функции SQL SQLite создаются именно с помощью этих же интерфейсов. Обратитесь к исходному коду SQLite, а именно к файлам date.c и func.c для примеров.
Динамически подключаемые библиотеки или DLL могут использоваться в качестве загружаемых расширений для SQLite.
9. Другие интерфейсы
В этой статье упоминаются только самые важные и наиболее часто используемые интерфейсы SQLite. Библиотека SQLite содержит множество других API, реализующих полезные функции, которые здесь не описаны. Полный список функций, составляющих интерфейс программирования приложений SQLite, можно найти в списке функций на странице Спецификации интерфейса C/C++. Обратитесь к этому документу за полной и авторитетной информацией обо всех интерфейсах SQLite.
Эта страница в последний раз была изменена 10 октября 2023 г. в 17:29:48 по UTC
SQLite is in the Public Domain.
https://sqlite.org/cintro.html