Databases/zh CN

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) français (fr) italiano (it) 日本語 (ja) português (pt) русский (ru) 中文(中国大陆) (zh_CN)

Databases portal

References:

Tutorials/practical articles:

Databases

Advantage - MySQL - MSSQL - Postgres - Interbase - Firebird - Oracle - ODBC - Paradox - SQLite - dBASE - MS Access - Zeos

本文介绍了Lazarus数据库。下表给出了 Lazarus 支持的数据库。

请只安装必要的数据库组件,如数据库需用到客户端库则应先安装客户端库。否则由于缺少文件,Lazarus 可能会无法启动。因为数据库组件无法卸载,一旦有问题 Lazarus 就得重装。

支持的数据库

数据库 软件包名 是否需要客户端库 是否需要服务器端 支持的版本 支持的平台
Advantage TAdsDataSet 10.1 以上 i386: Linux、Win32
DBase DBFLaz III+, IV, VII 所有
TurboPower FlashFiler FlashFiler - Win 32、(win64?)
In memory memds - 所有
In memory bufdataset - 所有
Firebird SQLdb 依赖于1 1 - 2.5 i386: Linux、Win32
(Visual) FoxPro DBFLaz 2.0, 2.5, 3.0 (不完全) 所有
Interbase SQLdb 4 - 6 i386: Linux、Win32
Microsoft SQL Server SQLdb 6- FPC 2.6.2+. Linux、macOS、Win32、可能 *BSD、可能 Solaris2
MySQL SQLdb 3.0 - 5.5 i386: Linux、Win32
ODBC SQLdb 有依赖条件 3.x 3 i386: Linux、Win32
Oracle SQLdb - -
Paradox TParadoxDataSet 最高至7级表(以上?) 所有
Paradox TParadox Win32
PostgreSQL SQLdb 6.6 - 8 i386: Linux、Win32
Sybase Adaptive Server Enterprise (ASE) SQLdb 任何 Linux、macOS、Win32、可能 *BSD, 可能Solaris2)
SQLite SQLdb sqlite3 所有
SQLite SQLite(3)Laz sqlite2、sqlite3 所有
Text 文件 sdf - 所有
ZMSQL zmsql ? ?

注1: 可在 Windows 和 Linux(可能也包括 macOS)中使用嵌入版的 Firebird,或者连到运行于 Windows/Unix/macOS/FreeBSD/其他 Firebird 支持平台中的 Firebird 服务器。

注2: 这些连接库用 FreeTDS 作为驱动程序,FreeTDS 的文档指出,至少应该可在这些平台下编译。Windows x86/x64 版本可在此下载:[1][2]

注3: 这里是指 ODBC 标准的版本,而非驱动程序或驱动程序管理器的版本号。大多数 DBMS 都带有 ODBC 3.x 驱动程序。

绑定数据库客户端

如果连接数据库需要客户端库,那就必须安装一下。不仅要在编程的计算机上安装,还要在所有运行应用程序的计算机上安装。请注意,某些数据库(特别是 MySQL)要求,编译时绑定的库版本必须与安装运行时的相同。在数据库开发方网站上,可以找到客户端库的安装方法(在 *nix 系统上是 .so 文件,在 Windows 上是 .dll 文件)。有关绑定的代码文件位于 fpc-sources 的 packages/base 目录中。内容基本就是一些客户端 API 的调用,比如 mysql_connect_database,每种数据库的调用各不相同。当然可以用这些代码文件编写数据库应用,但通常会增加很多工作量,且更容易出错,相比之下,使用 Lazarus 的 DB 组件会更为方便。

这些绑定软件包大多用硬编码链接客户端库。这意味着,如果在编译时包含了某个单元,但没有合适的客户端库,那么整个应用程序将无法链接。也就是说,如果计算机中没有安装 MySQL 客户端,程序中又使用了 mysql4.pp 单元,那么将无法生成可执行文件。虽然在安装了 MySQL 客户端库的计算机上编译成功,但在没有对应 MySQL 客户端库的其他机器上该程序仍然无法启动。换句话说:这些数据库要在开发机器上安装客户端库,并且还要将这些客户端库与应用程序一起安装。

为了避免这类问题,有些包能够动态链接到客户端库。在调用客户端库之前,必须先进行“初始化”。如果计算机上没有安装数据库客户端,初始化就会失败。如果客户端库连接就绪,那么之后需要执行“释放”操作。

数据集

数据集和数据库的区别

许多数据库编程新人无法区分数据集和数据库。现在数据库有很多种,比如 Firebird、Interbase、Oracle、Sybase、Microsoft Access 等。

最简单的概念就是,Lazarus 数据集(TDataset 的子类,如 TSQLQuery 等)可视为部分数据库查询记录的副本。假设用以下 SQL 语句打开查询:

   SQLQuery1.SQL.Text:= 'select * from table1 where id <=100';

打开 SQLQuery1,数据库 table1 中 id 小于等于 100 的记录将复制到 SQLQuery1 中。

通过 TDatasource(其又与 TDataset 连接),数据集中的数据可用数据库控件(如 TDBGrid、TDBEdit 等)进行可视化展示。

数据集中的数据可通过 insert、edit、delete、post 等命令(后续会讲解)进行修改,但这些操作都是基于数据集进行的,而不是直接在数据库表上完成。需要多做一步才能让改动持久性地存入数据库,比如调用 TDataSet.ApplyUpdates 或执行插入、更新 SQL 语句(与 TDataset.insert 或 TDataset.update 不同)。

通过设置数据库的事务属性,可在数据集关闭时将改动自动保存(或丢弃)。

数据集简介

在 Lazarus(或 Free Pascal)中,数据库的使用底层都基于 TDataSet 类展开。在应用程序中,TDataSet 类代表一张表或一个查询。然而,与很多其他基础类一样,TDataset 类不会直接用到,而会采用其某个子类。这些子类有很多,提供了对各种数据库的访问,例如本地 dBase 或文本文件,或者远程数据库如 PostgreSQL、Firebird、MySQL等。有些子类直接链接到数据库表,而另一些则使用其他组件或库来执行链接。

Dataset 的子类是非可视化组件,通常属于自由组件库(FCL)而不是 Lazarus 组件库(LCL)。

数据集既可通过纯代码方式使用,也可与可视化控件一起使用。典型的 Lazarus 数据库应用通常会同时使用这两种方式。不论哪种方式,第一步都是创建 TDataset 子类,进行初始化以连接到所需的表或查询,并执行 open 操作。可在运行时用代码完成,也可通过在窗体上放置组件并在设计时设置属性来完成。不同的 TDataset 子类在这方面的细节差异很大,因此请参阅数据库中的各个手册,了解操作步骤。

数据集打开后,会创建一些字段组件,每个字段(或打开的表、查询的列)都对应一个字段组件。每个字段组件都是 TField 的子类,根据字段的数据类型(如 TStringField)对应某个子类。

通过代码使用数据集对象

关于以编程方式访问数据集对象的详细说明,请参阅数据集和字段组件的用法,不过以下给出了非常简单的描述:

  • 用 TDataset 的子类打开表或查询,过滤出需查看的行,并在各行之间移动。
  • 用 TField 的子类:
    • 访问字段的定义信息
    • 访问当前行的字段值(通过 AsString、AsInteger 之类的属性)
  • 用以下方式访问 TDataset 子类的多个字段:
    • Fields 属性,如 Fields[0] 是第一个字段
    • FieldByName 方法,如 FieldByName('AGE') 返回数据库字段名为“AGE”的字段对象

字段类型的清单参见 Database_field_type

可视化(数据感知)控件的用法

若要在简单的“RAD”风格的 Lazarus 应用中使用数据库,通常会在设计时配置数据集子类,然后使用数据感知控件。这需要:

  • 在窗体中加入所选数据库的数据集子类及支撑组件,并打开(将“Active”属性设为true)。
  • 在窗体中加入一个TDataSource组件(位于Data Access 页),并“链接”至数据集组件(设置 DataSet属性)。
  • 在窗体中加入数据感知控件(位于Data Controls 页,全都要链接至 DataSource 组件(不是数据集组件)。
  • 大多数数据感知控件都是要链接到某个字段的,因此还需设置其 Field 属性。

更多有关控件的信息,请参阅下文中的 #Data Controls

数据集的状态

数据集可能处于多个状态。状态虽有很多(可以在源代码中查找 TDataSetState),但初学者需要了解的状态主要有:

状态 功能
dsInactive 已关闭
dsBrowse 用户可浏览,查看数据值
dsEdit 用户可编辑当前行的数据值。在执行 post 前不会保存。
dsInsert 加入新行,用户可设置值。在执行 post 前此行不会保存。

其他状态相对短暂,并且通常会“自动”处理,用于内部和更复杂的代码。如果只是查看数据库中的数据,并且在设计时打开数据集,那么很大程度上可以忽略状态的概念,因为大部分时间都会处于 dsBrowse 状态。不过大多数应用都需要修改数据。如果采用数据感知控件,则很多操作都会自动处理。例如TDBEdit控件在修改文本时,会将数据集置于 dsEdit 状态——除非原来就已处于 dsEdit 或 dsInsert 状态。如果在 dsEdit 或 dsInsert 状态时“滚动”到其他记录去,那么当前编辑的记录将被“提交”,数据集将回到 dsBrowse 状态。但如果是用代码访问数据集,那通常就必须用代码修改状态了。TDBNavigator控件(见下文)允许用户显式修改状态。

数据集的 UpdateStatus 属性

如果更新操作尚未写入数据库,UpdateStatus 标识了数据记录缓冲区的当前状态。

示例 如何检测 ApplyUpdates 要执行插入、更新还是删除操作:

procedure QueryAfterPost(DataSet: TDataSet);
begin
  case DataSet.UpdateStatus of
    usUnmodified : ShowMessage('Unmodified');
    usModified   : ShowMessage('Modified');
    usInserted   : ShowMessage('Inserted');
    usDeleted    : ShowMessage('Deleted');
  end;
end;
解释
  • usUnmodified: 记录未修改
  • usModified: 数据库中存在记录,本地已修改
  • usInserted: 数据库中不存在记录,本地已插入
  • usDeleted: 数据库中存在记录,本地已删除

提交和撤销

如果记录已完成编辑和插入,新值将保存在缓冲区中。

  • 调用数据集对象的 cancel 方法,将会删除新记录(插入操作时)或恢复原值(编辑操作时)。
  • 调用数据集对象的 post 方法,将会保存记录值(编辑操作时)或新记录(插入操作时)。 有些数据集子类会立即写入数据库,而另一些则会先存入更新列表中,后续再调用某个操作一次性写入数据库。最后,即便数据已经写入数据库,可能仍需调用“commit”方法让数据库执行持久性保存。所有这些操作,都因数据集子类的不同而有很大差异,因此请查看详细的文档。

插入新记录

要通过 TDataSet 子类插入新记录,应该使用 Insert 方法。先要设置字段值,最后再调用 Post 提交新记录,如下所示。

以下例子还展示了如何将文件数据插入 BLOB,也可以用 LoadFromStream 从流中加载数据。

  MyDataset.Insert;
  MyDataset.Fields[0].AsInteger := 4; //整数字段
  MyDataset.Fields[1].AsString := 'First Name'; //字符串字段
  (MyDataset.Fields[2] as TBlobField).LoadFromFile('SomeBlobfile.bin'); //blob 字段
  MyDataset.Post;

快速跳转至表中某条记录

已查出所有记录

如果是用 SELECT * FROM 查出了表中所有记录,然后要在记录之间快速跳转,那么就得先建索引再检索。更高效的做法是只查询需要的记录。

只查询所需记录

跳转至某条记录的一种做法,就是只查询这条记录,例如:

var
  MyDataset: TSQLQuery;
begin
  //...
  MyDataset.FieldDefs.Add('SessionId', ftLargeint);
  MyDataset.FieldDefs.Add('GameEvent', ftLargeint);
  MyDataset.FieldDefs.Add('TableId', ftInteger);
  MyDataset.FieldDefs.Add('LoggedIn', ftBoolean);
  MyDataset.FieldDefs.Add('PlayerId', ftInteger);
  MyDataset.Active := False;
  { Non-parameterized format; may run into issues with text containing ' and dates
  SQLText := Format('select * from "GameSession" WHERE "SessionId"=%d', [ASessionId]);
  }
  // 解决方案:带参数的查询
  // 如果是在循环中,其实 SQL.Text 只需设置一次,后续只要修改参数值即可。
  MyDataset.SQL.Text := 'select * from "GameSession" WHERE "SessionID"=:SessionID');
  MyDataSet.ParamByName('SessionID').AsLargeInt := ASessionID;
  try
    MyDataset.Active := True;
  except
    //...
  end;

然后可以读取数据如下:

 lPlayerId := MyDataset.Fields[4].AsInteger;

数据过滤

过滤操作可将数据集限制为所需子集(比如所有以 Smith 开头的姓氏)。

locate/lookup 方法

locate/lookup 可用于在记录之间跳转,但更多是在非SQL数据集中使用(如TParadoxDataSetTDbf)。

TSQLQuery 用法

TSQLQuery 详见 Working With TSQLQuery

数据导出

FPC/Lazarus 提供了将数据集以多种格式导出的工具包:

当然,也可以手动导出(比如用 fpspreadsheet 导出为 Excel 格式的 FPSpreadsheet#Converting_a_database_to_a_spreadsheet)。

Data Controls 控件组

使用这些控件需先加到窗体中,并至少应设置 datasource 属性。下面会介绍其他的关键属性。

Datasource 控件

此控件用于跟踪所关联控件当前位于哪条记录。Datasource 控件必须关联某个数据集控件(如 TSQLQuery)。

单字段控件

这些控件都是用于关联单个字段。除了设置 Datasource 外,还需设置字段名称。包括了:

  • DBText 控件 显示文本字段(只读,无边框)。
  • DBEdit 控件 以文本框的形式显示/编辑文本字段。
  • DBMemo 控件 以多行文本框的形式显示/编辑文本字段。
  • DBImage 控件 显示以 BLOB 格式存于数据库中的图片。注意:Lazarus 在将图像数据存入数据库的 BLOB 字段时,默认会写入包含图像类型的头部信息。这与 Delphi 不同。但可以让 TDBImage 兼容 Delphi,参见Delphi 用户的 Lazarus 指南
  • DBListBox 控件DBComboBox 控件 允许用户从其 Items 属性值列表中选取数据并插入数据库字段。
  • DBLookupListBox 控件DBLookupComboBox 控件,参见 TDBLookupComboBox 通过显示由另一张表字段查出的数据,允许用户从中选取值插入数据库字段中。尽管这些控件将结果存于单个字段中,但需要用到其他字段存放要查找的数据。注:至少 FPC 2.6.0 的 DBLookupComboBox 存在一个 bug,要求 listfield 也必须同在 Datasource 中。只要在 Datasource 的数据集中声明一个与 listfield 同名但不执行操作的计算字段,即可绕过这个问题。
  • DBCheckBox 控件 以选中/清除勾选框的形式显示/编辑 boolean 字段。
  • DBRadioGroup 控件 以单选按钮组的形式显示多项数据,由匹配上的某项数据读取/设置字段值。
  • DBCalendar 控件 以日历面板的形式显示/编辑日期字段。
  • DBGroupBox 控件

DBGrid 控件

此控件以行/列布局的形式显示多个字段——其实默认显示所有字段。但可在列集合中添加字段项,以便仅显示指定字段并设置列宽和标题。

DBGrid 文档 之外,Grids Reference Page#TCustomDBGrid 也包含更多信息。

TBNavigator 控件

此控件能让用户更直接地控制数据集。可以:

  • 移至下一条、上一条、第一条或最后一条记录。
  • 加入新记录(等效于调用数据集的 insert 方法)。
  • 将数据集设为 edit 模式。
  • 删除一条记录。
  • 提交或撤销当前改动。
  • 刷新数据(多用户数据库应用会比较有用)。

主要属性:

  • VisibleButtons:控制用户能够执行的操作。假定不允许删除,就可隐藏删除按钮。如果已有 DBGrid 连了同一个数据集,可能需要控制“下一条”和“上一条”按钮是否启用。
  • Width:如果所有按钮都不用显示,可能需要设置控件宽度。

FPC 数据库应用的测试

Free Pascal 数据库组件包含了一个基于 fpcunit 的代码测试框架 dbtestframework,可用于验证代码的功能是否正常。 参见 FPC 源码目录 source\packages\fcl-db\tests\。 Included 是个可运行各种数据库组件的测试框架,还包含了一些其他测试(比如数据库输出)。

请按以下步骤配置数据库并运行测试框架:

1. 将 source\packages\fcl-db\tests\database.ini.txt 保存为 source\packages\fcl-db\tests\database.ini

2. 修改 source\packages\fcl-db\tests\database.ini ,选取所需的数据库类型。

连接 Interbase/Firebird 数据库的示例:

[Database]
type=interbase

3. 在同一个文件中配置数据库参数。比如上面选的 Interbase:

[interbase]
connector=sql
connectorparams=interbase
; Database name/path (note: database needs to exist already)
; You can use aliases (see aliases.conf in your Firebird documentation)
name=testdb
user=sysdba
password=masterkey
; your hostname may very well differ:
; Leave blank if you want to use an embedded Firebird database
hostname=192.168.0.42

4. 编译运行 source\packages\fcl-db\tests\dbtestframework.pas (也可用 Lazarus 编译运行 GUI 版的代码 dbtestframework_gui) 若是在 Windows 中使用嵌入式数据库(如 Firebird 嵌入版或 sqlite),请先将所需的 DLL 文件复制到程序所在目录中。输出结果是 XML 格式(dbtestframework_gui 则会显示在屏幕上)。

更多详情请参阅 source\packages\fcl-db\tests\README.txt。

Lazarus 提供的数据库软件包

sqldblaz.lpk

sqldbcomponents.png

用于访问多种数据库,包括:

  • Interbase/Firebird
  • Microsoft SQL Server(Lazarus/FPC x64 Windows 版除外)
  • MySQL
  • Oracle(Lazarus/FPC x64 Windows 版除外)
  • PostgreSQL(Lazarus/FPC x64 Windows 版除外)
  • SQLite(支持 Spatialite 扩展)
  • Sybase ASE(Adaptive Server Enterprise,请勿与 Sybase ASA 混淆)(Lazarus/FPC x64 Windows 版除外)
  • 带 ODBC 驱动的所有数据库

所有组件(TSQLQuery、TSQLTransaction、TIBConnection、TODBCConnection、TOracleConnection、TMSSQLConnection、TMySQL40Connection、TMySQL41Connection、TMySQL50Connection、TPQConnection、TSybaseConnection)均位于组件面板的 SQLdb 页。

dbflaz.lpk

用于访问 dBase 和 FoxPro 数据库。详见 Lazarus Tdbf 教程。TDbf 组件位于组件面板的 Data Access 页

sqlitelaz.lpk

用于访问 SQLite 数据库。详见 Lazarus 数据库开发概述

sdflaz.lpk

TSdfDataSet 位于组件面板的 Data Access 页

lazreport.lpk

报告生成器的项目主页位于 http://lazreport.sourceforge.net/。 更多信息(其他链接)详见 这里。 LazReport 依赖 Printer4Lazarus 包。 Lazarus SVN 仓库纳入了 LazReport 11950 修订版。

lazdbexport.lpk

参见 lazdbexport

外部软件包/库

Zeos DataBase Objects

这些组件用于访问各种数据库。更多信息请参阅此处,自带 Zeos 教程

Pascal Data Objects

已有替代品。

支持:

  • MySQL 4.1 和 5.0
  • sqlite-2 和 sqlite-3
  • pgsql-8.1
  • interbase-5、interbase-6、firebird-1.0、firebird-1.5、firebird-1.5E、firebird-2.0、firebird-2.0E
  • mssql(Microsoft 库)和 sybase(FreeTDS 库)
  • oracle

数据库 API Pascal Data Objects 支持预编译语句、绑定和存储过程等功能,设计灵感来自 PHP Data Objects。所有代码和文档均在 Sourceforge: http://pdo.sourceforge.net

TPSQL

通过 TCP/IP 访问 PostgreSQL 数据库。详见 TPSQL

FIBL

用于访问 Interbase 和 Firebird 数据库。主页为 [3]

IBX

用于访问 Firebird 数据库,参见IBX

FBLib Firebird Library

FBLib 是个开源库,无数据感知能力,用于 Borland Delphi/Kylix、Free Pascal 和 Lazarus 直接访问 Firebird 关系数据库。

目前支持以下特性:

  • 直接访问 Firebird 1.0.x、1.5.x、2.x Classic 或 SuperServer
  • 跨平台 [Win32、Gnu/Linux、FreeBSD)
  • 自动选取 fbclient 或 gds32 客户端库
  • 带参数查询语句
  • 支持 SQL Dialect 1/3
  • LGPL 授权协议
  • 读取元数据
  • 简单的脚本解析
  • 最终 EXE 文件大小只增加 100-150 KB
  • 支持 BLOB 字段类型
  • 数据导出为 HTML SQL 脚本
  • 服务管理程序(备份、恢复、gfix 等)
  • 事件告警

文档见 FBLib 网站

Unified Interbase

UIB 支持访问 Interbase、Firebird 和 YAFFIL 数据库。主页为 www.progdigy.com。svn 仓库 https://uib.svn.sourceforge.net/svnroot/uib。

TechInsite Object 持久化框架 (tiOPF)

详见 tiOPF

访问 Advantage 的 TDataSet 子类

Advantage TDataSet 子类可用于连接 Advantage 数据库服务器(访问表)。Advantage 是一种灵活的、无需管理的嵌入式数据库,支持客户端/服务器或点对点方式访问 Clipper、FoxPro 和 Visual FoxPro 9 的 DBF 文件格式,同时还支持一种专有文件格式并提供迁移方案,以便用户能应用新特性。

主要特性:

  • 支持免费由点对点方式迁移至客户端/服务器模式。
  • 跨平台(客户端支持 Windows 和 Linux,服务器端支持 Windows、Linux 和 NetWare)。
  • 同时支持支持导航式访问和关系型 SQL 数据库式访问。
  • 全文本搜索引擎。
  • 表、索引、Memo 和通讯加密。
  • 与原生 TDataset 组件兼容。
  • 在线备份
  • 支持复制的数据库服务器

更多信息,请参阅网站 Advantage Database Server

ZMSQL:增强型 SQL 内存数据库

更多信息,请参阅 ZMSQL wiki

ZMSQL 是开源的、基于 TBufDataset 子类的增强型 SQL 内存数据库,专为 Free Pascal(FPC)设计,基于分号分隔的文本表进行操作。ZMSQL 完全用 Pascal 语言编写,不依赖任何外部库,SQL 功能用 JanSQL 引擎实现。

支持以下特性:

  • 文本表的加载/保存
  • 用 SQL 查询数据
  • 从其他数据集复制数据和模式
  • 字段定义可选择预定义或即时创建
  • 主/从表过滤
  • 参照完整性
  • 参数化查询

可下载的内容包括了源代码、演示应用(用于说明组件的功能)和自述文件。

参阅