SQLite и PHP
Данная статья предназначается PHP программистам, проявившим интерес к расширению SQLite. Статья представит читателю функциональность, предлагаемую расширением PHP SQLite, а также рассмотрит преимущества SQLite в сравнении с другими БД. Предполагается, что читатель знаком с основами PHP и SQL. Некоторый опыт работы с MySQL или PostgreSQL , будет способствовать лучшему пониманию того, о чём пойдёт речь.
В последнее время, вы, возможно, слышали о новом расширении для PHP: SQLite. Есть много причин, по которым SQLite может показаться лучшим достижением с тех пор, как научились резать хлеб. SQLite предлагает добротный SQL интерфейс к нереляционной базе данных и создаёт элегантную альтернативу громоздким интерфейсам других баз данных без потери функциональности или скорости, как можно было бы ожидать. Мы рассмотрим в статье это удивительное расширение и, будем надеяться, нам удастся подтвердить те преимущества, о которых, возможно, вы наслышаны.
SQLite – это встраиваемая библиотека в которой реализовано многое из стандарта SQL 92. Её притязанием на известность является как собственно сам движок базы, так и её интерфейс (точнее его движок) в пределах одной библиотеки, а также возможность хранить все данные в одном файле. Я отношу позицию функциональности SQLite где-то между MySQL и PostgreSQL. Однако, на практике, SQLite не редко оказывается в 2-3 раза (и даже больше) быстрее. Такое возможно благодаря высокоупорядоченной внутренней архитектуре и устранению необходимости в соединениях типа «сервер-клиент» и «клиент-сервер».
Всё это, собранное в один пакет, лишь немногим больше по размеру клиентской части библиотеки MySQL, является впечатляющим достижением для полноценной базы данных. Используя высоко эффективную инфраструктуру, SQLite может работать в крошечном объёме выделяемой для неё памяти, гораздо меньшем, чем в любых других системах БД. Это делает SQLite очень удобным инструментом с возможностью использования практически в любых задачах возлагаемых на базу данных.
Помимо скорости и эффективности у SQLite есть ряд других преимуществ, которые делают её идеальным решением для многих задач. Так как база данных SQLite по сути своей – обычные файлы, нет ни какой необходимости в дополнительных средствах администрирования требующих много времени на создание сложной структуры прав доступа для защиты пользовательских баз данных. Всё это уже автоматически поддерживается организацией прав доступа в самой файловой системе, это также подразумевает (в области ограничения пространства), что не требуется ни каких специальных правил для отслеживания заполнения дискового пространства пользователем. Преимущество для пользователей в том, что есть возможность создать такое количество баз данных, какое они себе пожелают плюс абсолютный контроль над всеми этими базами данных.
Факт, что база данных – это единственный файл, делает её легко переносимой. SQLite к тому же, устраняет необходимость в запуске дополнительных служебных процессов (daemons), которые могли бы «отъедать» значительное количество памяти и других ресурсов, даже в случае умеренного использования базы данных.
В качестве новейшего расширения БД, SQLite посчастливилось быть свободным от кода для обратной совместимости, в противоположность более старым расширениям, таким как MySQL , которые обязаны поддерживать устаревшую функциональность по причинам обратной совместимости. Это также позволяет новому расширению использовать самые новейшие разработки в PHP для достижения самого высокого уровня исполнения и функциональности. Разработчики облегчили задачу пользователям, создав расширение лёгким для перехода к нему от других систем БД, оставив интерфейс похожим на те, что уже были реализованы в PHP.
SQLite также поддерживает гибкий механизм для передачи ресурсов базы данных в процедурные интерфейсы, делая это одинаково лёгким для перехода из MySQL, где ресурс передаётся последним, и PostgreSQL, где он передаётся первым.
SQLite также отличает мощный объектно-ориентированный интерфейс, который может быть использован для эффективного извлечения данных из базы, избавляя вас от необходимости выполнения вашей собственной оболочки для процедурного интерфейса. Как показано в примере ниже, объектно-ориентированный интерфейс также позволяет вам избежать передачи всех ресурсов кучей.
query("BEGIN; CREATE TABLE foo(id INTEGER PRIMARY KEY, name CHAR(255)); INSERT INTO foo (name) VALUES('Ilia'); INSERT INTO foo (name) VALUES('Ilia2'); INSERT INTO foo (name) VALUES('Ilia3'); COMMIT;"); // выполняем запрос $result = $db->query("SELECT * FROM foo"); // проходим в цикле по ячейкам while ($result->hasMore()) < // получаем текущую ячейку $row = $result->current(); print_r($row); // переходим к следующей ячейке $result->next(); > // нет особой необходимости, так как PHP сам разорвёт соединение unset($db); ?>
В PHP 5.0 установка SQLite имеет свою особенность, так как и расширение и библиотека связаны вместе, поэтому всё, что вам необходимо сделать – это добавить –with-sqlite в строке конфигурирования. Я бы ещё порекомендовал установить SQLite, но только в случае если речь об откомпилированном бинарном файле, что позволит вам открывать базу и управлять ею без использования PHP. Это весьма полезно для отладки и выполнения различных одновременных команд, а также полезно для тестирования кода запросов. В будущем, довольно часто вы сможете обнаружить, что связанная библиотека SQLite немного «устарела», поэтому связка вашего PHP с внешней библиотекой позволит вам извлечь выгоду из последних исправлений и нововведений SQLite. Это также позволит вам в будущем обновлять вашу SQLite без перекомпиляции PHP.
Чтобы собрать расширение SQLite в качестве внешней библиотеки, просто используйте –with-sqlite=/path/to/lib/.
Мне также следует упомянуть, что расширение SQLite проходит исчерпывающую серию тестов, как для объектно-ориентированного, так и для процедурного интерфейсов. Тестируются каждая отдельная функция, и каждый метод поддерживаемый SQLite. Это великолепный источник примеров не только того, как работает каждый метод и каждая функция SQLite, но и ожидаемого вывода, позволяющего вам видеть конечный результат каждой операции.
Процедурный интерфейс к SQLite почти такой же, как у MySQL и других расширений БД. По большей части переход к SQLite потребует только изменить mysql/pq/etc… префикс функции на sqlite.
1 [id] => 1 [1] => Ilia [name] => Ilia ) */ > // закрываем соединение с базой sqlite_close($db); ?>
Собственно значительные отличия между SQLite и другими базами данных находятся в самом движке. В отличие от других БД в SQLite нет привязки к типам; все данные сохраняются как строки оканчивающиеся символом NULL, что лучше, чем двоичное представление данных в столбцах специального типа. По причине совместимости SQLite пока поддерживает тип спецификации в конструкциях CREATE TABLE, например, такой как INT, CHAR, FLOAT, TEXT и тому подобные, но реально их не использует. Внутри базы, SQLite только делает различие между строковыми и целочисленными данными во время сортировки. Поэтому, если вы не собираетесь сортировать данные, вы можете обойтись без указания специального типа полей при создании таблиц в SQLite.
«Безтиповая природа» SQLite делает сортировку и сопоставление данных в некотором роде медленнее, так как каждый раз SQLite будет вынуждена определять тип данных и применять либо строковый механизм сортировки/сравнения либо числовой. SQL таблицы часто требуют автоматически присваиваемый ключ для быстрого доступа к ячейкам, подразумевая возврат ссылки на последнюю добавленную ячейку. Для SQLite этот синтаксис, мягко говоря, бесполезен. Чтобы создать такую таблицу, вам понадобится объявить поле как INTEGER PRIMARY KEY, что более удобно чем указание специализированного типа или присваивание дополнительных свойств, которые указывают на то, что поле является автоинкрементным.
Как вы можете ожидать, SQLite несёт в себе много новых особенностей улучшающих исполнение и расширяющих функциональность. Одна из таких особенностей – возможность выполнять связанные запросы, которые подразумевают выполнение множественных запросов через функцию выполнения одного запроса. Это снижает количество задействованных функций PHP и таким образом увеличивает скорость работы скрипта. А также позволяет вам легко группировать блоки запросов внутри транзакций, улучшая выполнение в дальнейшем. Такая возможность может быть значительным фактором во время выполнения множественных обращений на запись в базу. Однако существует несколько пикантных особенностей, о которых не следует забывать.
Если какой-либо запрос в SQLite использует что-то введённое пользователем напрямую, вам следует предпринять дополнительные меры предосторожности для проверки такого ввода, чтобы пресечь нежелательный запрос. В противоположность MySQL, где такое может повлечь за собой лишь недоразумение при запросе к БД и выдать ошибку, в SQLite это позволит атакующему выполнить какой-нибудь запрос на вашем сервере с возможными плачевными последствиями. Если вы добавляете записи через блок запросов и хотели бы возвращать идентификатор, то sqlite_last_insert_rowid() хорошо справится с такой задачей, но вернёт идентификатор только последней записи. С другой стороны, при попытке определить какое количество ячеек было изменено, используя sqlite_changes(), мы получим результат, содержащий общее число ячеек изменённых всеми выполненными запросами. Если ваш блок запросов содержит SELECT, убедитесь что это самый первый запрос, в противном случае ваша окончательная выборка не будет содержать ячеек, возвращаемых этим запросом.
query("BEGIN; CREATE TABLE bar ( id INTEGER PRIMARY KEY, id2 ); INSERT INTO bar (id2) VALUES(1); INSERT INTO bar (id2) VALUES(2); COMMIT;"); // напечатает "2 insert queries" echo $db->changes()." insert queriesn"; // напечатает: "last inserted row id: 2" echo "last inserted row id: ".$db->last_insert_rowid(); ?>
SQLite3
To enable CURL and SQLITE3 on Windows with PHP 7.4 edit httpd.conf and php.ini as below:
# load php.ini from chosen directory
PHPIniDir «$/php»
# load PHP 7.4 on Windows
LoadModule php7_module «$/php/php7apache2_4.dll»
# load CURL on Windows
LoadFile «$/php/libssh2.dll»
# load SQLITE3 on Windows
LoadFile «$/php/libsqlite3.dll»
Now CURL and SQLITE3 are enabled and working fine on Windows on PHP 7.4.
As of PHP 5.4 support for Sqlite2 has been removed. I have a large web app that was built with sqlite2 as the database backend and thus it exploded when I updated PHP. If you’re in a similar situation I’ve written a few wrapper functions that will allow your app to work whilst you convert the code to sqlite3.
Firstly convert your DB to an sqlite3 db.
sqlite OLD.DB .dump | sqlite3 NEW.DB
Then add the following functions to your app:
function sqlite_open ( $location , $mode )
<
$handle = new SQLite3 ( $location );
return $handle ;
>
function sqlite_query ( $dbhandle , $query )
<
$array [ ‘dbhandle’ ] = $dbhandle ;
$array [ ‘query’ ] = $query ;
$result = $dbhandle -> query ( $query );
return $result ;
>
function sqlite_fetch_array (& $result , $type )
<
#Get Columns
$i = 0 ;
while ( $result -> columnName ( $i ))
<
$columns [ ] = $result -> columnName ( $i );
$i ++;
>
$resx = $result -> fetchArray ( SQLITE3_ASSOC );
return $resx ;
>
?>
They’re not perfect by any stretch but they seem to be working ok as a temporary measure while I convert the site.
Hope that helps someone
PHP doesn’t seem to support password protection for SQLite3. We can specify password on the db(I think) but you will still be able to open the DB without using a password so it is not working.
PHP 5.3.3 introduced sqlite3::busyTimeout(int milliseconds) which does not currently seem to be documented.
It believe it acts like sqlite::busyTimeout — that is it tells sqlite3 to call an internal busyHandler if SQLITE_BUSY is returned from any call which waits a short period and then retries. It continues to do this until milliseconds milliseconds have elapsed and then returns the SQLITE_BUSY status.
I don’t know whether the default 60 second value is in place if this function is not called.