admin / 18.01.2018
Содержание
Если вы уже имеете опыт работы с классами ADO.NET для MS SQL или Oracle, то освоение методики работы с классами для SQLite не вызовет у вас каких-либо затруднений. Для работы с файлом — источником данных используется класс SQLiteConnection, для работы с SQL-запросами используется класс SQLiteCommand, для получения и обработки результатов выполнения SQL-запросов используется класс SQLiteDataReader, либо SQLiteDataAdapter в связке с универсальными классами DataSet, DataTable и т.п.
Распространение данной статьи допускается в некоммерческих целях при условии размещения обратной веб-ссылки.
SQLite — компактная встраиваемая реляционная база данных. Исходный код библиотеки передан в общественное достояние. Является чисто реляционной базой данных.
Слово «встраиваемый» означает, что SQLite не использует парадигму клиент-сервер. Т.е. движок SQLite не является отдельно работающим процессом, с которым взаимодействует программа, а предоставляет библиотеку, с которой программа компонуется и движок становится составной частью программы.
Таким образом, в качестве протокола обмена используются вызовы функций (API) библиотеки SQLite. Такой подход уменьшает накладные расходы, время отклика и упрощает программу. SQLite хранит всю базу данных (включая определения, таблицы, индексы и данные) в единственном стандартном файле на том компьютере, на котором исполняется программа. Простота реализации достигается за счёт того, что перед началом исполнения транзакции записи весь файл, хранящий базу данных, блокируется; ACID [1]-функции достигаются в том числе за счёт создания файла журнала.
Несколько процессов или потоков могут одновременно без каких-либо проблем читать данные из одной базы. Запись в базу можно осуществить только в том случае, если никаких других запросов в данный момент не обслуживается; в противном случае попытка записи оканчивается неудачей, и в программу возвращается код ошибки. Другим вариантом развития событий является автоматическое повторение попыток записи в течение заданного интервала времени. Можно, также, ввести таймаут операций. Тогда подключение, столкнувшись с занятостью БД, будет ждать N секунду прежде, чем отвалиться с ошибкой SQLITE_BUSY.
Также с версии 3.7.0 присутствует режим WAL [2], с помощью которого можно испольовать одну и ту же базу несколькими приложениями, как на чтение, так и на запись.
В комплекте поставки идёт также функциональная клиентская часть в виде исполняемого файла sqlite3, с помощью которого демонстрируется реализация функций основной библиотеки.
Клиентская часть работает из командной строки, позволяет обращаться к файлу БД на основе типовых функций ОС.
Благодаря архитектуре движка возможно использовать SQLite как на встраиваемых системах, так и на выделенных машинах с гигабайтными массивами данных.
Формат файла базы данных является кросс-платформеным, что позволяет без проблем использовать одну и ту же базу на нескольких операционных системах. Также присутствует возможность хранения базы в памяти, без её записи на диск. Этот вариант используется по умолчанию для консольной утилиты sqlite3, если не указано имя файла.
Как известно, в своем развитии SQL устремился в разные стороны. Крупные производители начали впихивать всякие расширения. И хотя принимаются всякие стандарты, в реальной жизни все крупные БД не поддерживают стандартов полностью. Но зато имеют что-то свое.
Так вот, SQLite старается жить по принципу «минимальный, но полный набор». Она не поддерживает сложные штуки, но во многом соответствует SQL 92. И вводит некие свои особенности, которые очень удобны, но — не стандартны.
Неподдерживаются следующие возможности:
SQLite использует динамическое типизирование данных. Это значит, что тип столбца не определяет тип хранимого значения в этом поле записи. Т.е. в любой столбец можно занести любое значение.
Тип столбца определяет как сравнивать значения (нужно же их привести к единому типу при сравнении, скажем, внутри индекса). Но не обязывает заносить значения именно такого типа в столбец.
Допустим, мы объявили столбец как «A INTEGER». SQLite позволяет занести в этот столбец значения любого типа (999, «abc», «123», 678.525). Если вставляемое значение — не целое, то SQLite пытается привести его к целому. Т.е. строка «123» превратится в целое 123, а остальные значения запишутся «как есть».
Возможные типы полей: NULL, INTEGER, REAL, TEXT, BLOB.
Ситуация с покрытиями тестами исходного кода SQLite в некотором роде является легендой.
Это связно с тем, что тестами описано практически все возможные (и невозможные) ситуации. Кода, описывающего тесты, намного больше, чем кода реализующего SQLite. Естественно, что покрытие кода тестами 100%.
Сам же подход к тестированию использующийся разработчиками SQLite достоин подражания. И может быть взят как идеал, к которому следуют стремиться.
В качестве практического занятия для закрепления понимания реляционной модели и иллюстрации её ограниченности, мы рассмотрим пример создания структуры каталога товаров.
Для того чтобы запустить SQL-код необходимо выполнить следующую команду:
Далее откроется интерактивный SQLite-shell, куда можно вводить команды.
В этом примере мы рассмотрим как создать простую струкртуру каталога товаров.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
CREATETABLEcategory(nameTEXTNOTNULL);INSERTINTOcategory(name)VALUES('Тапки'),('Самолёты'),('Ноутбуки');CREATETABLEproduct(nameTEXTNOTNULL,priceNUMERICNOTNULL,categoryREFERENCEScategory(rowid));INSERTINTOproduct(name,price,category)VALUES('Босоножки',1.17,1),('Вьетнамки',2.36,1),('Макасины',4.99,1),('ИЛ-2',556000,2),('Суперджет 100',1500000,2),('Ту-160',25000000,2),('Dell',590,3),('Lenovo',200,3),('Sony',437,3);
|
В этом примере мы рассмотрим, как расширить существующую структуру под новые требования.
Требования будут следующими:
ALTERTABLEproductADDsizeINTEGER;ALTERTABLEproductADDcapacityINTEGER;ALTERTABLEproductADDprocessorTEXT;
|
Сущетсвенным недостатком данного подхода является тот факт, что поля одних категорий товаров являются обязательными для других категорий.
Т.е., например, поле «размер», которое добавлено для категории «Тапки», становится обязательным и для товаров из категории «Самолёты» и «Ноутбуки».
Классическая реляционная модель не позволяет удобно применить отдельные поля для разных категорий. Можно, конечно, использовать поле типа BLOB и складывать туда всё, что душе вздумается, но тогда потеряются такие прелести реляционных СУБД, как индексы, тригеры (либо они очень усложнятся) и фильтрация в запросах.
Можно ещё, как вариант, оставить базовые поля в одной таблице, а остальные вынести в дополнительные, связав их внешними ключами. Но это, опять же, ненужное усложнение.
Поэтому предлагаю оставить замечательную реляционную базу SQLite в покое. Она замечательно справляется с возложенными на неё обязанностями. Благодаря чему и является, пожалуй, самой популярной встраиваемой базой данных в мире.
Сейчас мы научимся работать с параметрами при создании запроса.
Когда мы используем параметризованные запросы, мы используем местозаполнители вместо прямого написания значений в SQL запросе. Запросы с указанием параметров отдельно увеличивают безопасность и производительность.
Python модуль sqlite3 поддерживает два типа заполнителей: знаки вопроса и именованные заполнители.
Мы обновляем цену одной машины. В этом примере кода, мы используем заполнители типа «знак вопроса».
Знаки вопроса ? являются заполнителями для значений. Значения добавляются на его место.
Свойство rowcount возвращает количество обновленных строк.
В нашем случае, одна строка была обновлена.
Такой подход программирования и создания запрос к базе данных увеличивает безопасность приложения. webmartsoft.ru/web-razrabotka.html — профессиональная веб разработка выполняет качественные и безопасные проекты которые позволяют своим клиентам не бояться за сохранность данных своего сайта.
Была обновлена цена машины.
Второй пример использует запрос с параметрами с именованными заполнителями.
Мы выбираем название и цену машины, используя именованные заполнители.
Именованные заполнители начинаются с символа двоеточия.
SQLite — это база данных, чем-то похожая на MySQL. Принципиальное отличие SQLite от других БД в том, что вся база представляет собой один файл. Если в MySQL база хранится где-то в дебрях сервера и недоступна для переноса, то в SQLite с этим всё до безобразия просто: один файл — одна база.
Конечно же, сервер должен поддерживать драйвер SQLite (также как и любой другой БД), но как правило сейчас с этим проблем нет.
SQLite позволяет привычно работать с базой через SQL, создавать таблицы, поля и т.д. В целом можно сказать, что SQLite ни в чем не уступает привычной MySQL, за исключением, пожалуй более медленной работы с «тяжелыми» sql-запросами по обновлению данных (insert и update). Но, опять же, это для высоконагруженных сайтов.
Огромным плюсом SQLite будет её легкая переносимость. Скопировать файл — что может быть проще? Не нужно заботиться о бэкапах, как в MySQL, не нужно создавать на сервере пользователя с паролем, не нужно создавать саму базу. С SQLite просто берём и пользуемся.
Для работы с базой данных в PHP лучше использовать PDO — Объекты данных PHP — это т.н. абстракция, которая предлагает единый интерфейс для работы с разными базами. В теории, используя PDO, можно переключиться на любую базу, не переделывая SQL-запросы, например с MySQL на SQLite. Меняются только параметры подключения.
Таким образом SQLite будет подключаться через PDO. Для этого ничего не требуется, поскольку сам PDO уже в составе PHP, а драйвер SQLite, как правило, также включен на серверах.
Но, прежде, чем приступать к программированию, нужно создать саму базу. Например для MySQL существует phpMyAdmin, через который можно выполнять различные операции. Для SQLite также есть похожие разработки, но я покажу, как можно это делать через браузер FireFox. Для этого потребуется только установить дополнение SQLite Manager.
Чтобы добавить это дополнение в основное меню FireFox («гамбургер»), нажмите Изменить и перетащите мышью икноку в меню.
На этом SQLite Manager установлен и можно им пользоваться.
Для начала создадим новую базу данных. В SQLite — это отдельный файл, который будет иметь расширение . SQLite Manager предложит указать каталог, где будет храниться этот файл. Выберите или создайте новый каталог. Для нас это пока не имеет особого значения.
В результате будет создан sqlite-файл с новой базой.
Этот файл можно перемещать (и переименовывать) куда угодно, а после открывать командой меню Базы данных — Подключить базу данных.
Теперь нужно создать таблицу (или таблицы) в базе данных.
SQLite Manager автоматом создаёт служебные таблицы sqlite_XXX. Мы их не трогаем и нам они не мешают.
Таблица в БД — это то место, где хранится структурированная информация. Таблица должна иметь набор полей с заданными свойствами. Например поле может быть integer — для целых чисел, или text — для текста. Количество полей может быть произвольным и определяется только задачей вебмастера.
Пусть, например, у нас будет таблица с полями
После того, как таблица создана, обратите внимание на блок «SQL-оператор создавший этот объект». В нем будет SQL-запрос, которым можно создать таблицу. Он может пригодится, если требуется создать таблицу в базе через PHP.
На вкладке «Просмотр и Поиск» можно редактировать таблицу. Создадим для примера две строчки, где поле slug будет и . Это будут две страницы: главная и сайт/contact.
Поле hits будет содержать счетчик просмотров страницы. Текст может быть любым.
Всё, база готова, теперь можно её использовать.
Поставим задачу. Пусть у нас будет простенький сайт, который будет выдавать по короткой ссылке (slug) соответствующий текст и количество просмотров.
Если мы делаем это на локальном сервере, то пусть сайт будет в каталоге sqlite. В нём подкаталог db, куда мы и скопируем наш pages.sqlite.
Роутинг мы можем сделать, как описано в предыдущей статье PHP-роутинг (Routing) для новичков. Файл
AddDefaultCharset UTF-8 Options -Indexes <IfModule mod_rewrite.c> RewriteEngine on RewriteBase /sqlite/ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule (.*) /sqlite/index.php?$1 [QSA,L] </IfModule>
В index.php сам роутинг будет описан одной строчкой:
$page = ($p = key($_GET)) ? $p : ‘home’;
То есть будет содержать ссылку или для главной.
Дальше алгоритм будет такой:
Я намеренно упрощаю алгоритм, чтобы не усложнять php-код.
Существуют два варианта работы с БД. Первый — это нативный php-код. Он не очень сложный, но обилие параметров немного напрягает. Поэтому второй вариант — использование дополнительных библиотек-оберток. С ними код становится лаконичней.
Приведу код в первом варианте:
<?php $page = ($p = key($_GET)) ? $p : ‘home’; try { $pdo = new PDO(‘sqlite:db/pages.sqlite’); $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $sql =’SELECT * FROM pages WHERE slug=:page LIMIT 1′; $sth = $pdo->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY)); $sth->execute(array(‘:page’ => $page)); $rows = $sth->fetchAll(); print_r($rows); // здесь выводим данные } catch(Exception $e) { echo $e->getMessage(); } # end of file
Для второго варианта я использовал php-библиотеку с сайта labaka.ru, которую разместил в подкаталог lib.
Код :
<?php $page = ($p = key($_GET)) ? $p : ‘home’; require ‘lib/sqlite.php’; try { $db = new Db(‘db/pages.sqlite’); $row = $db->queryRow(‘SELECT * FROM pages WHERE slug=:page LIMIT 1’, array(‘:page’ => $page)); if ($row) { echo $row[’text’]; echo ‘<br>Просмотров: ‘ . $row[’hits’] . ‘<br>’; $db->update(‘pages’, array(‘hits’ => $row[’hits’] + 1), ‘id=:id’, array(‘:id’ => $row[’id’])); } } catch(Exception $e) { echo $e->getMessage(); } # end of file
Данный пример будет выводить для разных адресов разный текст и при этом будет работать счетчик просмотров. Если требуется добавить новую страницу, то её достаточно создать в базе. Для удобства, в SQLite Manager можно подключить базу прямо из каталога сайта.
Здесь следует отметить пару важных моментов.
В первую очередь, вся работа с PDO должна заключаться в блок . Таким способом отлавливаются сообщения об ошибках.
Данные, которые отправляются в sql-запрос должны проходить через валидацию. В PDO, когда используется предподготовка данных (PDO::prepare), выполняется принудительное экранирование параметров. Это позволяет защититься от возможных SQL-инъекций.
Когда происходит подключение базы данных SQLite, в случае отсутствия файла базы, он будет создан автоматически. На этом базируется создание базы сразу после его подключения и создание нужных таблиц первым sql-запросом (о котором я написал выше).
Еще одно замечание по SQLite. Поскольку база это файл, то его можно скачать по URL прямо через браузер. Поэтому каталог с SQLite-файлами лучше защищать через строчкой . Или же размещать выше чем основной www-каталог.
SQLite может пригодится для небольших задач, которые требуют небольшой базы данных: счетчики, голосования, мета-данные страниц и т.п.
Вы можете скачать файлы к этой статье.
FILED UNDER : IT