Sign in Join
Wiki copytemporary

SQLite/ru

English · Español · Français · Polski · Русский · 中文(中国) · 日本語

Поддержка SQLite и FPC/Lazarus

SQLite - это встроенная (не серверная) однопользовательская база данных, которую можно использовать в приложениях FPC и Lazarus. Для доступа к SQLite из программ FPC/Lazarus можно использовать различные драйверы. Все драйверы нуждаются в библиотеке SQLite/dll в исполняемом каталоге (который может быть каталогом вашего проекта или, например, (projectdir)/lib/architecture/ в зависимости от настроек вашего проекта Lazarus) (и распространяется вместе с вашим исполняемым файлом) для работы.

Это также может быть необходимо включить в ваш каталог Lazarus IDE. См. ветку форума и особенно внимательно прочитайте про TSQLite3Dataset и TSQLiteDataset ниже

В большинстве дистрибутивов Linux по умолчанию установлен sqlite3 (например, libsqlite3.so.0), но для дистрибутивов Ubuntu, по крайней мере, также требуется соответствующий пакет Dev. Оба должны быть установлены через системный менеджер пакетов и помечены как зависимость, а не распространяться вместе с вашим приложением.

Win64: см. предупреждение здесь о неиспользовании определенных версий FPC/Lazarus Win64.

Прямой доступ к SQLite

Вы можете использовать простой способ подключения SQLite к Lazarus. Компоненты называются LiteDAC. Компоненты доступа к данным SQLite (LiteDAC) - это библиотека компонентов, которая обеспечивает встроенное подключение к SQLite из Lazarus (и Free Pascal) в Windows, macOS, iOS, Android, Linux и FreeBSD как для 32-разрядных, так и для 64-разрядных платформ. LiteDAC предназначен для программистов, которые могут разрабатывать действительно кроссплатформенные настольные и мобильные приложения баз данных SQLite без необходимости развертывания каких-либо дополнительных библиотек.

Вы можете скачать пробную версию этого коммерческого продукта по адресу _https://www.devart.com/litedac/download.html (LiteDAC 4.4 for Lazarus (FreePascal))

Встроенный SQLDB

FPC/Lazarus предлагает встроенные компоненты SQLDB, которые включают поддержку баз данных SQLite (TSQLite3Connection) с вкладки SQLdb в Палитре компонентов, которые позволяют, например, создавать графические интерфейсы пользователя с такими компонентами базы данных, как TDBGrid. Преимущество использования SQLDB заключается в том, что довольно легко перейти на другую базу данных, такую ​​как Firebird или PostgreSQL, без особых изменений в программе. Подробнее см. ниже.

Поддержка Spatialite

Spatialite - это ГИС-расширения SQLite, которые можно использовать из SQLDB. См. Spatialite.

Поддержка шифрования SQLite

В последних версиях FPC (реализованных в марте 2012 г.) SQLDB включал поддержку некоторых расширенных версий SQLite3, которые шифруют файл базы данных SQLite с использованием алгоритма AES. Используйте свойство пароля, чтобы установить ключ шифрования.

Примеры:

sqlite3backup

sqlite3backup - это модуль, поставляемый с FPC (не в Lazarus, но может использоваться программно), который обеспечивает функции резервного копирования/восстановления для SQLite3. Он использует SQLDB sqlite3conn.

Zeos

Zeos

SQLitePass

Компоненты SQLitePass. Последнее обновление кода в 2010. Последняя активность на форуме в 2011.

TSQLite3Dataset и TSQLiteDataset

Существуют также отдельные пакеты TSQLiteDataset (модуль sqlite) и TSQLite3Dataset (модуль sqlite3ds); см. ниже описание того, как их использовать. Посетите домашнюю страницу sqlite4fpc, чтобы найти справочник по API и другие руководства.

TSqliteDataset и TSqlite3Dataset являются потомками TDataSet, которые обращаются к базам данных sqlite 2.8.x и 3.x.x соответственно. Для новых проектов вы, вероятно, будете использовать TSQlite3Dataset, поскольку текущая версия SQLite 3.x.

Ниже приведен список основных преимуществ и недостатков по сравнению с другими драйверами/методами доступа FPC/Lazarus SQLite:

Преимущества:

Недостатки:

Note: Учитывая вышеизложенное, многие пользователи будут использовать SQLDB или Zeos из-за преимуществ, если им не нужен низкоуровневый доступ к библиотеке SQLite.

Использование компонентов SQLdb со SQLite

Эти инструкции сосредоточены на особенностях SQLDB (TSQLite3Connection) для SQLite. Для общего обзора ознакомьтесь с SqlDB: Howto, где есть полезная информация о компонентах SQLdb.

См. Учебник1 по SQLdb для обучения создания программы с поддержкой базы данных с графическим интерфейсом пользователя, которая написана для SQLite/SQLDB (а также для Firebird/SQLDB, PostgreSQL/SQLDB, в основном любой СУБД, поддерживаемой SQLDB).

Мы будем использовать комбинацию из трех компонентов из вкладки Lazarus SQLdb: TSQLite3Connection, TSQLTransaction и TSQLQuery. TSQLQuery действует как наш TDataset; в простейшем случае это просто одна из наших таблиц. Для простоты: убедитесь, что у вас уже есть существующий файл базы данных SQLite, и вам не нужно создавать новый сейчас. TSQLite3Connection можно найти в модуле sqlite3conn, если вы хотите объявить его самостоятельно или работаете в FreePascal.

Эти три компонента связаны друг с другом как обычно: в TSQLQuery установите свойства Database и Transaction, в TSQLTransaction установите свойство Database. В компонентах Transaction и Connection особо нечего делать, большинство интересного будет сделано в TSQLQuery. Настройте компоненты следующим образом:

TSQLite3Connection:

Note: Чтобы установить полный путь к библиотеке (если вы поместите свою sqlite dll/so/dylib в место, где ОС ее не найдет, например каталог приложения в Linux/OSX), вы можете установить «SQLiteLibraryName» свойство (ДО того, как будет установлено какое-либо соединение, например, в событии OnCreate главной формы)

, например:

pascal
SQLiteLibraryName:='./sqlite3.so';

TSQLQuery:

После того, как все вышеперечисленное будет настроено правильно, вы сможете использовать TSQLQuery, как и любой другой TDataset, либо программно манипулируя его данными, либо помещая TDatasouce в форму, подключая его к TSQLQuery, а затем используя контуры данных, такие как TDBGrid и т.п.

Creating a Database

Метод TSQLite3Connection.CreateDB, унаследованный от родительского класса, на самом деле ничего не делает; чтобы создать базу данных, если файл еще не существует, вам просто нужно записать данные таблицы, как в следующем примере:

(Код, извлеченный из примера sqlite_encryption_pragma, который поставляется с Lazarus 1.3 и новее)

pascal
var
  newFile : Boolean;
begin

  SQLite3Connection1.Close; // Убедитесь, что соединение закрыто при запуске

  try
  //Поскольку мы делаем эту базу данных впервые,
  // проверяем, существует ли уже файл    
  newFile := not FileExists(SQLite3Connection1.DatabaseName);

    if newFile then
    begin
      // Создаем базу данных и таблицы
      try
        SQLite3Connection1.Open;
        SQLTransaction1.Active := true;

        // Здесь мы настраиваем таблицу с именем "DATA" в новой базе данных.
        SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
                    ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
                    ' "Current_Time" DateTime NOT NULL,'+
                    ' "User_Name" Char(128) NOT NULL,'+
                    ' "Info" Char(128) NOT NULL);');

        // Создание индекса на основе идентификатора в таблице "DATA"
        SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');

        SQLTransaction1.Commit;

        ShowMessage('База данных успешно создана.');
      except
        ShowMessage('Невозможно создать новую базу данных');
      end;
    end;
  except
    ShowMessage('Невозможно проверить, существует ли файл базы данных');
  end;
 end;

Создание определяемых пользователем порядка сортировки

pascal
// utf8-callback функция сравнения с учетом регистра
function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareStr(UTF8Decode(S1), UTF8Decode(S2));
end;

// utf8-callback функция сравнения без учета регистра
function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareText(UTF8Decode(S1), UTF8Decode(S2));
end;

// регистрируем порядок сортировки с помощью SQLite3 API (требуется модуль sqlite3dyn):
sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
// или используем метод TSQLite3Connection:
CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);  

// теперь мы можем использовать порядок сортировки без учета регистра в SQL, например:
// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'á'

// но это не работает для оператора LIKE
// чтобы поддерживать также оператор LIKE, мы должны перегрузить функцию LIKE по умолчанию, используя sqlite3_create_function ()
// http://www.sqlite.org/lang_corefunc.html#like

Создание пользовательских функций (UDF)

pascal
// пример перегрузки функции LOWER() по умолчанию на функцию, предоставляемую пользователем
// чтобы запустить эту демку, вы должны добавить модули sqlite3dyn и ctypes в ваше предложение uses
// и добавить константу 'SQLITE_DETERMINISTIC' со значением $800

procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
var S: AnsiString;
begin
  SetString(S, sqlite3_value_text(V[0]), sqlite3_value_bytes(V[0]));
  S := UTF8Encode(AnsiLowerCase(UTF8Decode(S)));
  sqlite3_result_text(ctx, PAnsiChar(S), Length(S), sqlite3_destructor_type(SQLITE_TRANSIENT));
end;

// регистрируем функцию LOWER() с помощью SQLite3 API (требуется модуль sqlite3dyn):
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);

SQLite3 и даты

Значения по умолчанию для местного времени вместо UTC

CURRENT_TIME, CURRENT_DATE и CURRENT_TIMESTAMP возвращают текущую дату и/или время в формате UTC. Для местной даты и/или времени мы можем использовать:

text
 DEFAULT (datetime('now','localtime')) for datetime values formated YYYY-MM-DD HH:MM:SS
 DEFAULT (date('now','localtime')) for date value formated YYYY-MM-DD
 DEFAULT (time('now','localtime')) for time value formated HH:MM:SS

Устранение неполадок SQLDB и SQLite

pascal
interface
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);overload;
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);overload;  
 
implementation
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
// Эта процедура обновляет набор данных и помещает курсор на последнюю запись
// Используется, если Dataset не гарантирует сортировку набора данных по первичному ключу автоинкремента
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  //Получаем последний вставленный ID в базе данных 
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  //Теперь возвращаемся к соответствующей строке
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Обновляемся и возвращаемся к соответствующей строке
    pDataset.Locate(pKeyField,vLastID,[]);
  end;
end;
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
//Эта процедура обновляет набор данных и помещает курсор на последнюю запись
//Используется только в том случае, если DataSet гарантированно отсортирован по первичному ключу с автоинкрементом.
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Опасно!
    pDataSet.Last;
  end;
end;

procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery); //Если ваш набор данных отсортирован по первичному ключу
end;  

procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //если вы не уверены, что набор данных всегда сортируется по первичному ключу
end;

Vacuum и другие операции, которые необходимо выполнять вне транзакции

Кажется, что SQLDB всегда требует подключения, но некоторые операции, такие как Pragma и Vacuum, должны Быть сделано вне транзакции. Хитрость заключается в том, чтобы завершить транзакцию, выполнить то, что вы должны, и начать транзакцию еще раз (чтобы не запутать sqldb):

pascal
  // коммит любых ожидающих операций или использование «свежего» соединения sql
  Conn.ExecuteDirect('End Transaction');  // Завершение транзакции, начатой SQLdb
  Conn.ExecuteDirect('Vacuum');
  Conn.ExecuteDirect('Begin Transaction'); //Запуск транзакции для использования SQLdb

Использование TSQLite3Dataset

В этом разделе подробно описано, как использовать компоненты TSQLite2Dataset и TSQLite3Dataset для доступа к базам данных SQlite (от Luiz Américo luizmed(at)oi(dot)com(dot))br

Требования

Перед запуском проекта lazarus убедитесь, что:

Как использовать (базовое использование)

Установить пакет, который находится в каталоге /components/sqlite (см. инструкции здесь) (прим.перев.: на момент перевода статьи это можно сделать через стандартный установщик пакетов Лазаруса из меню Package(Пакеты) --> Install/Uninstall Package (Установка/Удаление пакетов) --> справа в окне Available for installation (Доступные для установки) выбираем sqlite3laz 0.4 --> ниже жмем кнопку Install Selection (Установить выбранное) --> жмем в самом низу кнопку Save and rebuild IDE (Сохранить и пересобрать IDE)).

Во время разработки установите следующие свойства:

Создание Table (Dataset)

Дважды щелкните значок компонента или используйте пункт 'Create Table'(Создать таблицу) во всплывающем меню, которое появляется при нажатии правой кнопки мыши. Будет показан простой редактор таблиц с пояснениями.

Вот все типы полей, поддерживаемые TSqliteDataset и TSqlite3Dataset:

Получение данных

После создания таблицы или с помощью ранее созданной таблицы откройте набор данных с помощью метода Open. Если свойство SQL не было установлено, будут извлечены все записи из всех полей, то же самое можно получить, если вы зададите SQL следующим образом:

pascal
SQL := 'Select * from TABLENAME';

Применение изменений к базовому файлу данных

Чтобы использовать функцию ApplyUpdates, набор данных должен содержать по крайней мере одно поле, которое удовлетворяет требованиям для первичного ключа (значения должны быть UNIQUE, а не NULL)

Сделать это можно двумя способами:

Если установлено одно из двух условий, просто вызовите

pascal
ApplyUpdates;

Note: Если заданы оба условия, поле, соответствующее PrimaryKey, используется для применения обновлений.

Note: Установка PrimaryKey в поле, которое не является первичным ключом, приведет к потере данных при вызове ApplyUpdates, поэтому перед его использованием убедитесь, что выбранное поле не содержит значений Null и Unique.

Пример Master/detail

Различные примеры отношений master/detail (например, отношения между клиентом и заказами):

Примечания

Общие примеры можно найти в SVN каталоге fpc/fcl-db/src/sqlite.

See also


From the Free Pascal wiki, page "SQLite/ru", as it stood on 2021-11-16 after a change by Slawek, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 3, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.