Sign in Join
Wiki copytemporary

SQLite/zh CN

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

SQLite 和 FPC/Lazarus 支持

SQLite 是一个嵌入式的 (非服务器的) 、单用户的、可以在 FPC 和 Lazarus 应用程序中使用的数据库。许多驱动可以用于在FPC/Lazarus程序中访问SQLite数据库。 所有的驱动都需要SQLite库/dll在可执行目录(可以是你的项目目录,或者例如 (projectdir)/lib/architecture/ ,这取决于你的Lazarus项目设置)(并与你的可执行文件一起发行)以正常运作。

这可能也需要悲包含在你的 Lazarus IDE 目录. 详见 1 并继续阅读 TSQLite3Dataset 和 TSQLiteDataset See below

大多数 Linux发行版默认安装有 sqlite3 (例如 libsqlite3.so.0),但至少基于Debian的发行版也需要匹配的Dev包才能获得 libsqlite3.so。两者都应通过系统包管理器安装并标记为依赖项,而不是与应用程序一起分发。

Win64: 请看 这里 关于不使用某些 FPC/Lazarus Win64 版本的警告

直接访问 SQLite

你可以使用一种简单的方式在 Lazarus 上连接到 SQLite。名为 LiteDAC 的组件。SQLite 数据访问组件(LiteDAC)是一个提供原生的SQLite连接的组件库,在 Windows, macOS, iOS, Android, Linux 和 FreeBSD 的32位及64位上的的Lazarus(和 Free Pascal)。LiteDAC 为编程者开发真正跨平台的桌面和移动的 SQLite 数据库应用程序而无需部署其它额外的库而设计。

你可以在这里下载一份这个商业产品的适用版本 Lazarus components.

内建的 SQLDB

FPC/Lazarus 提供内建的 SQLDB 组件,它提供 SQLite 数据库 (TSQLite3Connection) 从 Component Palette 的 SQLdb tab,它允许你例如使用形如 Component Palette 的数据库组件来创建图形界面。使用 SQLDB 的有点是它可以很容易地更换到一个不同的数据库例如 FireBird 或 PostgreSQL,而不必太多修改你的程序。详情请见下文。

Spatialite support

Spatialite are GIS extensions to SQLite which you can use from within SQLDB. See Spatialite.

SQLite 加密的支持

在近期的 FPC 版本 (从 FPC 3.0.0 开始, 在 2012年3月 实现), SQLDB 包括了对 SQLite3 的某些扩展版本的支持,这些版本使用 AES 算法加密 SQLite 数据库文件。 使用“Password”属性设置加密密钥。

示例:

根据您使用的内容,可能还需要在“5.0 C interface”处单独启用加密如此处所写, 在访问加密数据库之前,您需要使用产品密钥调用 sqlite3_activate_see() 。

sqlite3backup

sqlite3backup 是 FPC 提供的一个单元(不在 Lazarus 中,但可以通过编程方式使用),为 SQLite3 提供备份/恢复功能。 它使用 SQLDB 的 sqlite3conn。

Zeos

Zeos

SQLitePass

SQLitePass 组件. 2010年最后一次编码. 上次社区活跃在2011年.

TSQLite3Dataset 和 TSQLiteDataset

还有单独的TSQLiteDataset(单元 sqlites)和TSQLite3Dataset(单元 sqlite3ds)包; 有关如何使用它们的说明,请参阅下文。 访问 sqlite4fpc 主页 查找 API 参考和更多教程。

TSqliteDataset 和 TSqlite3Dataset 是 TDataSet 后代,分别访问 2.8.x 和 3.x.x sqlite 数据库。 对于新项目,您可能会使用 TSQlite3Dataset,因为 SQLite 3.x 是当前版本。

下面列出了与其他 FPC/Lazarus SQLite 驱动程序/访问方法相比的主要优点和缺点:

优点:

缺点:

Note: 鉴于上述情况,许多用户会因为 SQLDB 或 Zeos 的优点而使用 SQLDB 或 Zeos,除非他们需要对 SQLite 库进行较低级别的访问

使用SQLdb组件以使用SQLite

这些说明重点关注 SQLite 的 SQLDB (TSQLite3Connection) 细节。 有关一般概述,请查看 SqlDBHowto,其中包含有关 SQLdb 组件的一些有用信息。

有关创建为 SQLite/SQLDB(以及 Firebird/SQLDB、PostgreSQL/SQLDB,基本上任何 RDBMS SQLDB 支持)编写的支持 GUI 数据库的程序的教程,请参阅 SQLdb Tutorial1。

我们将使用 Lazarus SQLdb 选项卡中的三个组件的组合:TSQLite3Connection、TSQLTransaction 和 TSQLQuery。 TSQLQuery 充当我们的 TDataset; 在最简单的情况下,它仅代表我们的一张表。 为了简单起见:确保您已经拥有一个现有的 SQLite 数据库文件,并且现在不需要创建新的文件。 如果您想自己声明或者在 FreePascal 中工作,TSQLite3Connection 可以在“sqlite3conn”单元中找到。

这三个组件像平常一样相互连接:在 TSQLQuery 中设置属性 Database 和 Transaction,在 TSQLTransaction 中设置属性 Database。 Transaction 和 Connection 组件中没有太多可做的事情,大部分有趣的事情将在 TSQLQuery 中完成。 配置组件如下:

TSQLite3Connection:

注意:要设置完整的库路径(如果您将 sqlite dll/so/dylib 放置在操作系统找不到它的地方,例如 Linux/OSX 上的应用程序目录),您可以设置 SQLiteLibraryName 属性(在建立任何连接之前,例如在主窗体的 OnCreate 事件中),如下所示:

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

TSQLQuery:

正确设置上述所有内容后,您现在应该能够像任何其他 TDataset 一样使用 TSQLQuery,方法是通过以编程方式操作其数据,或者将 TDatasouce 放置在表单上,将其连接到 TSQLQuery,然后使用 TDBGrid 等数据控件。

创建一个数据库

从父类继承的TSQLite3Connection.CreateDB方法实际上什么也不做; 要在尚不存在文件的情况下创建数据库,您只需编写表数据,如下例所示:

(从 Lazarus 1.3 及以上版本附带的 sqlite_encryption_pragma 示例中提取的代码)

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表中的id创建索引
        SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');

        SQLTransaction1.Commit;

        ShowMessage('Succesfully created database.');
      except
        ShowMessage('Unable to Create new Database');
      end;
    end;
  except
    ShowMessage('Unable to check if database file exists');
  end;
 end;

创建用户定义的排序规则

pascal
// utf8 区分大小写的比较回调函数
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 不区分大小写的比较回调函数
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 运算符,我们必须使用 sqlite3_create_function() 重载默认的 LIKE 函数
// http://www.sqlite.org/lang_corefunc.html#like

创建用户定义的函数

pascal
// 使用用户提供的函数重载默认 LOWER() 函数的示例
// 要运行此演示,您必须将单元'sqlite3dyn'和'ctypes'添加到您的uses-clause中
// 并添加一个值为 $800 的 const 'SQLITE_DETERMINISTIC'

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 (requires sqlite3dyn unit):
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);

SQLite3 与日期

http://www.sqlite.org/datatype3.html#datetime。

默认值采用当地时间而不是 UTC

CURRENT_TIME、CURRENT_DATE 和 CURRENT_TIMESTAMP 返回当前 UTC 日期和/或时间。 对于本地日期和/或时间,我们可以使用:

  DEFAULT (datetime('now','localtime')) 对于格式为 YYYY-MM-DD HH:MM:SS 的日期时间值
  DEFAULT (date('now','localtime')) 对于格式为 YYYY-MM-DD 的日期值
  DEFAULT (time('now','localtime')) 格式为 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);
//此过程刷新数据集并将光标定位到最后一条记录
//如果数据集不能保证按自动增量主键排序,则使用
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  //获取数据库中最后插入的ID
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  //Now come back to respective row
  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;

真空和其他必须在事务外完成的操作

SQLDB 似乎总是需要connection,但某些操作(例如 Pragma 和 Vacuum)必须在transaction之外完成。 诀窍是结束transaction,执行你必须做的事情然后在此开始transaction(这样sqldb就不会混淆:)

pascal
  // 提交任何挂起的操作或使用“新”sql连接
  Conn.ExecuteDirect('End Transaction');  // 结束由 SQLdb 启动的transaction
  Conn.ExecuteDirect('Vacuum');
  Conn.ExecuteDirect('Begin Transaction'); // 启动一个transaction供 SQLdb 使用

使用 TSQLite3Dataset

本节详细介绍如何使用 TSQLite2Dataset 和 TSQLite3Dataset 组件访问 SQlite 数据库。 by Luiz Américo luizmed(at)oi(dot)com(dot)br

要求

在初始化一个Lazarus项目之前, 确保:

怎样使用 (基础用法)

安装在 /components/sqlite 目录中找到的包 (见说明: here)

在设计时,设置以下属性:

创建表 (Dataset)

双击组件图标或使用单击鼠标右键时出现的弹出菜单中的“创建表”项。 将显示一个简单的不言自明的表格编辑器。

以下是 TSqliteDataset 和 TSqlite3Dataset 支持的所有字段类型:

检索数据

创建表后或使用之前创建的表,使用 Open 方法打开数据集。 如果未设置 SQL 属性,则将检索所有字段中的所有记录,如果将 SQL 设置为:

pascal
SQL := 'Select * from TABLENAME';

将更改应用到基础数据文件

要使用ApplyUpdates函数,数据集必须至少包含一个满足主键要求的字段(值必须是UNIQUE且不为NULL)

可以通过两种方式做到这一点:

如果设置了两个条件之一,则只需调用

pascal
ApplyUpdates;

Note: 如果两个条件都设置了,则使用 PrimaryKey 对应的字段来应用更新。

Note: 将PrimaryKey设置为非主键的字段,如果调用ApplyUpdates,将导致数据丢失,因此在使用之前请确保所选字段不包含Null和Unique值。

大纲/详细信息示例

主/详细关系的各种示例(例如客户和订单之间的关系):

评论

通用示例可以在 fpc/fcl-db/src/sqlite SVN 目录中找到

也可以看看


From the Free Pascal wiki, page "SQLite/zh CN", as it stood on 2023-07-15 after a change by Iruanp, 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 2, last changed by WikiArchive .

Talk about this page

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