Знакомство с SQLite
Автор: Вадим К
Вступление
Часто на форумах, да и здесь на сайте спрашивают, какую базу данных выбрать. Хочу сегодня представить вам ещё один движок БД, у которого есть свои преимущества.
Называется этот движок SQLite. Итак, его преимущества:
- бесплатный + открытый исходный код;
- достаточно быстр;
- не нуждается в дополнительной настройке на клиентской машине – распространять вместе с приложением нужно только одну dll;
- лоялен к программисту;
- возможность работать с компакт-диска (т.е. в режиме "только для чтения");
- возможность работать с гостевого аккаунта;
- никаких записей в реестр и на диск (кроме dll и файла базы данных), никаких настроек сетевых протоколов;
- многоплатформенный: есть поддержка для многих языков (с 3 версии формат файла БД совместим для различных ОС и языков);
- сама dll зависит только от одной системной dll - MSVCRT.DLL, которая всегда есть в системе;
- синтаксис SQL достаточно хорошо соответствует стандарту – вы можете взять любую книгу, где описывается ANSI SQL 92 и пользоваться. Или посмотреть на сайте http://www.sqlite.org/lang.html.
Но есть и недостатки:
- не рекомендован для баз большого размера (эксперты не рекомендуют более 200 Мб);
- есть только два типа данных – целое автоинкримент и строка (всё остальное – эмулируется через строки);
- не предназначен для многопользовательского использования (хотя это и возможно).
Начальные приготовления
Для работы с этой базой нам в обязательном порядке понадобится сама dll. Её можно скачать с сайта http://www.sqlite.org/ или взять в архиве к статье. С dll можно работать напрямую, но куда удобнее использовать обертку в виде классов. Есть обертка, которая подобна делфийскому TTable, есть и драйвер для ODBC, который позволяет работать с базой посредством TADOTable. И если первый вариант ещё интересен, то вариант с использованием через ADO лишен смысла – многие «вкусности» теряются.
В архиве вы найдете разные классы для работы. Я работаю с одним с них, и дальше буду описывать его. Главное преимущество – он без компонентов. Хотя кому-то это и покажется сложным, но можно, например, делать консольные приложения.
Также неплохо иметь ещё одну программу – программу для редактирования баз данных. Что-то в виде Database Desktop, только для SQLite. Такая программа есть и она бесплатна. Скачать можно здесь http://sqlitebrowser.sourceforge.net/ или опять же, взять в архиве. Хотя программа и проста, свою работу выполняет отлично. Мы не будем составлять базу в программе, а пойдём как настоящие кодеры - научимся создавать её в своей программе.
Работа с БД
Для примера мы создадим маленькую базу из одной таблицы. У нас будет одно автоинкрементое поле и два строковых.
Запускаем Delphi. Создаём новый проект. В папку с проектом копируем файлы sqlite3.pas, sqliteTable3.pas и sqlite3.dll. Дальше их надо подключить к проекту. Выбираем в меню Project – Add to project и добавляем эти файлы. Также не забываем сделать File – Use unit и выбрать эти же файлы, но предварительно переключившись на главный юнит.
После строки {$R *.dfm} допишем Var sldb: TSQLiteDatabase; - это будет глобальный объект для работы с базой. Хотя лучше сделать его свойством формы. Кто понимает – сделает :-)
Делаем подключение к базе. Для этого впишем такой код в FormCreate:
procedure TForm1.FormCreate(Sender: TObject); begin sldb := TSQLiteDatabase.Create('test.db'); try if not sldb.TableExists('test') then sldb.ExecSQL('CREATE TABLE Test (id INTEGER PRIMARY KEY, T1 TEXT, T2 TEXT)'); except ShowMessage('При создании базы произошла ошибка.'); Application.Terminate; end; end;
Согласитесь, всё предельно просто. На ADO, если бы базы не было, пришлось бы делать дополнительную работу и писать процедуру не на одну строку.
Суть этого кода следующая – открыть файл test.db. Потом проверить, есть ли в нём таблица test. Если нет – создать, выполнив запрос. Если файла не будет, то он будет создан. Если же при создании таблицы у нас что-то не сложилось – закроем приложение.
Также не забываем, что за собой надо чистить.
procedure TForm1.FormDestroy(Sender: TObject); begin sldb.Free; end;
Теперь научимся добавлять записи. Ставим кнопку с заголовком "Create records" ("Создать записи") и создадим для неё такой обработчик
procedure TForm1.Button1Click(Sender: TObject); const n = 100; // сколько записей хотим добавить var i: integer; t: cardinal; //для подсчёта времени begin t := GetTickCount; for i := 0 to n - 1 do sldb.ExecSQL('insert into test (t1,t2) values("'+inttostr(random(1000))+'","'+inttostr(random(1000))+'")'); t := GetTickCount - t; ShowMessage(Format('Добавленно %d записей за %d мс',[n,t])); end;
Теперь научимся отображать записи и выполнять запросы к базе.
Поставим TMemo, TEdit и кнопку "Select" ("Выбрать"). По нажатию на кнопку будем искать записи в поле T1, которые начинаются на те же цифры, что мы ввели в Edit, и будем их выводить.
procedure TForm1.Button2Click(Sender: TObject); var sltb:TSQLiteTable; i:integer; begin Memo1.Lines.BeginUpdate; try Memo1.Clear; sltb := sldb.GetTable('select t1,t2 from test where t1 like "'+Edit1.Text+'%"'); try for i := 0 to sltb.Count - 1 do begin Memo1.Lines.Add(sltb.FieldAsString(0)+', '+sltb.FieldAsString(0)); sltb.Next; end; finally sltb.Free; end; finally Memo1.Lines.EndUpdate; end; end;
Как можно заметить, ничего особенного. Всё очень похоже на то, что доступно в BDE.
А картинки как?
Не знаю почему, но с другими базами добавление картинок для меня – большая трагедия. И если ещё с BDE всё спокойно, то с ADO сплошные приключения :-)
В SQLite есть специальный тип поля – BLOB (он есть и во многих других БД).
Итак, общий алгоритм добавления бинарных данных в базу:
- Добавить запись с помощью INSERT. Но не включать бинарное поле (BLOB).
- Узнать ID добавленной записи (есть специальный метод у TSQLiteDatabase – GetLastInsertRowID – возвращает значение последнего добавленного автоинкрементого поля. Его имя не обязано быть ID. Важно только наличие)
- С помощью UPDATE обновить данное поле, добавив к нему изображение/BLOB (для этого опять же есть метод UpdateBlob. Он принимает два параметра. Первый – сиквел-выражение вида "UPDATE моя_таблица SET поле_блоба = ? WHERE поле_id = сохранённый_id". Надо только заполнить по шаблону 4 слова. Второй параметр – подготовленные в TStream данные. Например, var f: TFileStream; … f := TFileStream.Create('FileName',fmOpenRead));.
Саму реализацию оставляю как домашнее задание :-)
Результаты
Всего несколько строк, а имеем сколько преимуществ. На этом движке я построил несколько приложений, используя его для хранения информации. По субъективным ощущениям работает база в несколько раз быстрей, чем аналогичная на Access. Приложение при старте запускается моментально, ведь ему не надо инициализировать COM-объекты.
Пробуйте, дерзайте, экспериментируйте!
Автор: Вадим К
Статья добавлена: 31 января 2008
Следующая статья: Создание интерфейса с использованием PNG-графики »
Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.
Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:
Ссылка для форумов (BBCode):
Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:43}} (буква a — латинская) — только адрес статьи (URL);
{{статья:43}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).
Поделитесь ссылкой в социальных сетях:
Комментарии читателей к данной статье
Репутация: нет |
delphi7776 (14 января 2016, 16:22): как сделать escape string при добавлении записей?
|
Репутация: +66 |
DNK (11 апреля 2012, 15:54) | 1 отзыв: Столкнулся с ошибкой, если в пути к файлу базы имеются кирилические символы, всплывает ошибка "Failed to open database "$$$$$$$$" : unable to open database file." С помощью Вадима выяснил, что проблема заключается в необходимости передавать имя файла в кодировке "UTF-8", а не Win.
Index: SQLite3.pas =================================================================== --- SQLite3.pas (revision 2418) +++ SQLite3.pas (working copy) @@ -57,7 +57,7 @@ TSQLiteResult = ^PChar; TSQLiteStmt = Pointer; -function SQLite3_Open(dbname: PChar; var db: TSqliteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_open'; +function SQLite3_Open(dbname: PUTF8String; var db: TSqliteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_open'; function SQLite3_Close(db: TSQLiteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_close'; function SQLite3_Exec(db: TSQLiteDB; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_exec'; function SQLite3_Version(): PChar; cdecl; external 'sqlite3.dll' name 'sqlite3_libversion'; Index: SQLiteTable3.pas =================================================================== --- SQLiteTable3.pas (revision 2418) +++ SQLiteTable3.pas (working copy) @@ -123,6 +123,7 @@ var Msg: pchar; iResult: integer; + utf8Str: UTF8String; begin inherited Create; @@ -130,7 +131,8 @@ Msg := nil; try - iResult := SQLite3_Open(PChar(FileName), Fdb); + utf8Str := AnsiToUtf8(FileName); + iResult := SQLite3_Open(PUTF8String(utf8Str), Fdb); if iResult <> SQLITE_OK then if Assigned(Fdb) then |
Репутация: нет |
JerryJkee^^ (24 мая 2010, 13:56): здравствуйте, подскажите плиз, как подключиться к удаленной БД SQLite 2.1 ??
|
Репутация: +40 |
Ерёмин А.А. (17 мая 2010, 12:51): Тоже встречался с этой проблемой. Вроде бы, что-то вручную там подправил и всё заработало.
|
Репутация: нет |
Azzi (16 мая 2010, 17:28): Ну вот а теперь, самый волнующий вопрос. Данная статья написана для 2007 делфи. И не прикрепленные фаилы не будут работать с версиями 2009 и выше. Обидно. Но если в двух словах, то:
В D2007 PChar = PAnsiChar В D2009 PChar = PWideChar и В D2007 String = AnsiString В D2009 String = WideString Не могу выложить исправленные версии фаилов. Но сам нашел их здесь http://www.itwriting.com/repos/sqlitewrapper/trunk/ удачи, коллеги YT vjue |
Репутация: нет |
LauNCheR (21 июля 2009, 22:01): Ничего так, спасибо! Помогли разобраться с sqlite немного. С БД раньше вообще не работал.
Только программа слегка некорректная, вроде. У вас: Memo1.Lines.Add(sltb.FieldAsString(0)+', '+sltb.FieldAsString(0)); а надо: Memo1.Lines.Add(sltb.FieldAsString(0)+', '+sltb.FieldAsString(1)); |
Оставлять комментарии к статьям могут только зарегистрированные пользователи.