SQLite для кроссплатформенной разработки в Delphi XE2
Дата: 8.10.2011 | Комментариев: 0 | Просмотров: 6663
Уже больше года прошло с момента публикации статьи "SQLite в Delphi 2010." Надо сказать, что рассмотренный в статье SQLiteWrapper я успешно использовал и в Delphi 2010 и в Delphi XE. Знаю, что есть ещё несколько подобных реализаций для работы с SQLite в Delphi, но почему-то этот wrapper мне понравился более всего - небольшой по размеру, удобный в использовании, простой в изучении. Что ещё для счастья нужно? Никакого паролирования мне для баз SQLite мне не требовалось поэтому использовал себе и использовал разработку Тима Андерсона (Tim Anderson). Но, как говориться, прогресс не стоит на месте и вот вышла Delphi XE2, сама SQLite вроде бы тоже несколько раз "апнулась". Соответственно, поддержка x64, FireMonkey и прочие довольно обширные нововведения в Delphi, а также обновление библиотеки SQLIte.dll внесли свои коррективы в разработку...и мой любимый враппер дал сбой. Нет, он конечно и раньше требовал, например, передачу в параметры методов исключительно AnsiString, но это, можно сказать, мелочи. А тут вдруг после сборки проекта под XE2 перестали работать некоторые методы, например FieldAs..., Bind и пр. Посыпались исключения. Первым делом глянул в репозиторий, но там оказалась ревизия от февраля месяца, т.е. для XE2 не предназначенная, да и среди нововведений значился только бэкап баз данных.
Решил немного пошерстить Сеть в поисках подходящего враппера для SQLite в Delphi XE2. И был приятно удивлен, что разработка Тима Андерсона жива, здорова и даже теперь уже "пышет" кроссплатформенностью. Правда изменились/исчезли некоторые методы, но и добавилось достаточно. Собственно эту находку я сегодня и решил представить в своем блоге.
Итак, первым делом заходим в репозиторий на Google Code и скачиваем исходники себе на компьютер.
Если не знаете как работать с Google Code - читаем "Совместная работа над проектом. Основы работы с Google Code" и "Совместная работа над проектом. Работа в проектах на Code.Google".
Итак, что появилось в обновленной версии. Прежде всего - это поддержка Unicode. Теперь все методы работают не с AnsiString как это было в предыдущей версии, а со String, что избавляет от некоторых лишних "телодвижений" при работе с SQLite в Delphi.
Появились типы TDate и TDateTime.
Для класса TSQLiteDatabase:
Добавлен метод Attach для добавления к текущему соединению нового файла базу данных (подробнее см. документацию);
Добавлен классовый метод AddNewSupportedColumnType;
Удален метод BindData
Удалены несколько перегруженных методов, таких как GetTable, GetTableString, GetTableValue
Для класса TSQLiteTable
Добавлено свойство IsLastRow: boolean
Удалено свойство FieldAsString и вместо него добавлено аналогичное - FieldValByNameAsString (зачем? Посмотрим ниже)
Для класса TSQLiteUniTable
Добавлен новый метод FindField(const AFieldName: string): TSQLiteField;
Добавлены новые свойства FieldsVal, FieldByName, FieldByNameAsString, FieldIndex, SQL, Stmt
Добавлен новый класс TSQLitePreparedStatement
Добавлен новый клсс TSQLiteField
Ну, а раз появились новые классы, методы и свойства, то их надо изучить и попробовать использовать в работе. Для примера создадим простенькую базу данных, состоящую из одной таблички и будем читать/писать данные, по возможности использую новые типы данных.
Для создания базы данных можете выбрать любую из программ для работы с SQLite, например, рассмотренных в статье "Обзор программ для администрирования баз данных SQLite.". Я буду пользоваться бесплатной версией SQLite Expert.
Итак, создаем новую базу данных с названием TestSQLite.db и таблицей:
CREATE TABLE [TestTable] (
[id] INTEGER PRIMARY KEY AUTOINCREMENT,
[StringRow] TEXT,
[NumberRow] INTEGER,
[DateTimeRow] DATETIME);
Теперь создаем новое приложение в Delphi XE2, бросаем в папку с проектом модели SQLite3 и SQLiteTable3 и библиотеку sqlite3.dll.
Добавим на форму приложения 2 кнопки, 4 Label'а и Memo. Внешний вид приложения будет такой:
Теперь создадим три переменные в секции private класса формы:
Base: TSQLiteDatabase;
Table: TSQLiteUniTable;
Stmt: TSQLitePreparedStatement;//новый класс
На OnCreate будем подключаться к БД и получать количество строк в БД. Обработчик будет следующим:
procedure TForm13.FormCreate(Sender: TObject);
var Rows: integer;
begin
Base := TSQLiteDatabase.Create(ExtractFilePath(Application.ExeName) +
'TestSQlite.db');
Stmt := Base.GetPreparedStatement('SELECT count(id) FROM [TestTable]');
Table:=Stmt.ExecQuery();
Label4.Caption := Table.FieldsAsString[0];
end;
Теперь напишем обработчик кнопки для записи 1000 значений в БД. Для этого будем использовать в запросе параметры следующим образом:
procedure TForm13.Button1Click(Sender: TObject);
var
i: integer;
t: cardinal;
begin
t := GetTickCount;
Stmt.SQL :=
'INSERT INTO [TestTable] ([StringRow], [NumberRow], [DateTimeRow]) VALUES (:str, :int, :date)';
for i := 0 to 999 do
begin
Stmt.ClearParams;
Stmt.SetParamInt(':int', i);
Stmt.SetParamText(':str', IntToStr(i));
Stmt.SetParamDateTime(':date', Now);
Stmt.PrepareStatement(Stmt.SQL);
Stmt.ExecQuery();
end;
t := GetTickCount - t;
Label1.Caption := Format('Добавленно %d записей за %d мс', [i, t]);
end;
Посмотрим за какое время при таком подходе в БД запишется 1000 записей:
Больше 86 секунд. Медленно. Попробуем ускорить процесс. Дописываем в обработчик следующий код:
Base.BeginTransaction;
try
for i := 0 to 999 do
begin
[...]
end;
finally
Base.Commit;
end;
Проверяем скорость:
Менее 1 секунды на запись 1000 элементов. Неплохо? Транзакции в SQLite рулят =)
Двигаемся далее. Теперь попробуем прочитать первые 1000 записей из базы данных и вывести эти значения в Memo. Так как объект типа TSQLitePreparedStatement у нас уже есть, то нам достаточно сменить SQL-запрос и получить таблицу данных (TSQLiteUniTable). Кстати, при чтении посмотрим в действии новый класс TSQLiteField. Итак, обработчик кнопки на чтение данных из базы:
procedure TForm13.Button2Click(Sender: TObject);
const cStr = '%s - %d - %s';
var t:cardinal;
begin
Memo1.Lines.Clear;
Stmt.SQL:='SELECT * FROM TestTable LIMIT 1000';
Table:=Stmt.ExecQuery;
t := GetTickCount;
while not Table.EOF do
begin
{получаем по имени поля объект TSQLiteField и получаем значение}
Memo1.Lines.Add(Format(cStr,[Table.FieldByName['StringRow'].AsString,
Table.FieldByName['NumberRow'].AsInteger,
Table.FieldByName['DateTimeRow'].AsString]));
Table.Next;
end;
t := GetTickCount - t;
Label2.Caption := Format('Получено 1000 записей за %d мс', [t]);
end;
У меня чтение 1000 записей и вывод их в Memo заняло чуть больше 1,5 секунд. В приведенном выше коде я использовал работу с новым классом TSQLiteField в котором содержатся методы и свойства необходимые для работы с полями БД.
Итак, что можно сказать по поводу обновленной библиотеки для SQLite в Delphi XE2:
Библиотека стала более соответствовать реальному положению дел в Delphi - поддержка Unicode тому подтверждение.
Новые классы библиотеки, такие как TSQLitePreparedStatement и TSQLiteField, на мой взгляд, делают работы с программой ещё более прозрачной. Так, с помощью TSQLiteDatabase мы можем подключаться к БД, делать резервное копирование, приаттачивать другие базы и т.д., с помощью TSQLitePreparedStatement - управлять запросами к базе данных и получать объекты TSQLiteUniTable, на, а с TSQLiteUniTable мы получаем доступ к не обходимым полям таблицы и, используя возможности TSQLiteField работать непосредственно со значениями полей. По-моему вполне логично и удобно.
Напомню ещё раз, что исходники библиотеки Вы можете скачать здесь.
Информация взята с сайта webdelphi.ru
Все используемые на сайте статьи, файлы и логотипы компаний принадлежат их законным владельцам. Если вы являетесь правообладателем "SQLite для кроссплатформенной разработки в Delphi XE2" и не желаете, чтобы ваша информация находилась на нашем сайте, напишите нам и эта информация будет удалена.
Категория: Публикации » Публикации - Delphi
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.