Delphi 数据库开发终极指南
本教程将分为以下几个部分,由浅入深,适合不同水平的开发者:
- 核心概念与环境准备
- 第一部分:基础篇 - 使用 dbExpress 连接数据库
- 第二部分:进阶篇 - 使用 FireDAC 连接任意数据库
- 第三部分:高级篇 - 数据绑定与用户界面
- 第四部分:实战篇 - 构建一个完整的 CRUD 应用
- 学习资源与最佳实践
第一部分:核心概念与环境准备
在开始编码之前,我们需要了解一些核心概念并准备好我们的开发环境。
核心概念
- 数据库引擎: 管理数据存储、检索和操作的软件,MySQL, SQL Server, PostgreSQL, SQLite 等。
- 数据访问组件: Delphi 提供的、用于与数据库引擎通信的组件,它们是 Delphi 应用和数据库之间的桥梁。
- dbExpress: 跨平台、轻量级的驱动架构,它是一种单向连接(只读或只写),性能高,但功能相对简单,适合快速开发和报表等场景。
- FireDAC: 目前是 Delphi 官方推荐、功能最强大的数据访问框架,它支持几乎所有主流数据库(包括云数据库),具有高性能、功能丰富、跨平台的特点,本教程将以 FireDAC 为主。
- 数据集: 内存中数据的虚拟表示,它像一个表格,有行和列,并提供了导航、编辑、过滤数据的方法,常见的数据集组件有
TDataSet,TTable,TQuery,TClientDataSet,在 FireDAC 中,核心是TFDQuery和TFDTable。 - 数据绑定: 将 UI 控件(如
TDBGrid,TDBEdit)与数据集组件自动关联起来,当你在 UI 上修改数据时,数据集会自动更新;当你在代码中移动数据集指针时,UI 会自动刷新,这是 RAD (Rapid Application Development) 的精髓。
环境准备
- 安装 Delphi: 确保你安装了 Delphi 10.4 Sydney 或更高版本(版本越新,FireDAC 支持越好)。
- 安装数据库服务器:
- SQLite (推荐初学者): 无需安装,一个
.db文件就是一个数据库,非常轻量,适合单机应用。 - MySQL / PostgreSQL: 功能强大的客户端/服务器数据库,适合多用户应用。
- InterBase: Embarcader 官方数据库,与 Delphi 集成度极高。
- SQLite (推荐初学者): 无需安装,一个
- 安装数据库驱动:
- 对于 dbExpress: Delphi 安装时会自带一些驱动(如 SQLite, InterBase, MySQL),如果需要其他驱动(如 PostgreSQL),需要手动从 Embarcadero 官网下载并安装。
- 对于 FireDAC: FireDAC 的驱动是 “开箱即用” 的!你只需要在系统中安装好对应的数据库客户端库(连接 MySQL 需要
libmysqlclient或MySQL Connector/C)即可,FireDAC 会自动找到它们。
第二部分:基础篇 - 使用 FireDAC 连接数据库
我们将以最简单的 SQLite 为例,演示如何使用 FireDAC 建立连接。
步骤 1: 创建新项目
- 打开 Delphi,选择
File -> New -> VCL Forms Application - Delphi。 - 保存项目为
FDProject.dpr和Unit1.pas。
步骤 2: 添加 FireDAC 组件
-
打开
Tool Palette(工具栏)。 -
找到
FireDAC页面。 -
从该页面拖拽以下组件到窗体上:
TFDConnection: 用于建立和管理与数据库的物理连接。TFDQuery: 用于执行 SQL 语句并返回结果集。TDataSource: 作为 UI 控件和数据集之间的桥梁。
你的窗体现在看起来应该像这样:
步骤 3: 配置 TFDConnection
-
选中窗体上的
FDConnection1组件。 -
在
Object Inspector(对象检查器) 中,找到ConnectionDefName属性。 -
点击下拉框,选择
Add New Connection...。 -
在弹出的
FireDAC Connection Editor窗口中:- Server: 选择
SQLite。 - Database: 点击 按钮,选择一个位置,创建一个新的数据库文件,
C:\Temp\MyFirstDB.db,如果文件不存在,FireDAC 会自动创建。 - 其他选项 保持默认即可。
- 点击
Test Connection按钮,如果成功,会提示 "Connection definition created successfully"。 - 点击
OK保存连接定义。
- Server: 选择
-
FDConnection1.ConnectionDefName属性会自动填充为你刚刚创建的连接名称(如SQLite_DB1)。
步骤 4: 创建数据表
我们还没有表,所以需要先创建一个,最简单的方法是使用代码。
- 双击窗体,创建
FormCreate事件。 - 在
FormCreate事件中编写以下代码来创建一个Employees表:
procedure TForm1.FormCreate(Sender: TObject);
begin
// 1. 打开连接
if not FDConnection1.Connected then
FDConnection1.Connected := True;
// 2. 准备并执行创建表的 SQL 语句
FDQuery1.Connection := FDConnection1;
FDQuery1.SQL.Text := 'CREATE TABLE IF NOT EXISTS Employees (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT, ' +
'Name VARCHAR(100), ' +
'Position VARCHAR(100), ' +
'Salary REAL)';
try
FDQuery1.ExecSQL; // 执行不返回结果集的 SQL (如 INSERT, UPDATE, CREATE)
ShowMessage('表 Employees 创建成功!');
except
on E: Exception do
ShowMessage('创建表失败: ' + E.Message);
end;
end;
运行一次程序,关闭后,你的 C:\Temp\MyFirstDB.db 文件中就包含了 Employees 表。
第三部分:进阶篇 - 使用 FireDAC 进行数据操作
现在我们有了连接和表,可以开始进行增删改查操作了。
查询数据
// 在 FormCreate 事件中,创建表之后添加以下代码
FDQuery1.SQL.Text := 'SELECT * FROM Employees';
FDQuery1.Open; // 打开数据集,准备读取数据
// FDQuery1 中就有了数据,可以通过代码遍历
while not FDQuery1.Eof do
begin
ShowMessage('员工: ' + FDQuery1.FieldByName('Name').AsString);
FDQuery1.Next; // 移动到下一条记录
end;
// 操作完成后关闭
FDQuery1.Close;
插入数据
// 使用参数化查询防止 SQL 注入,这是最佳实践
FDQuery1.SQL.Text := 'INSERT INTO Employees (Name, Position, Salary) VALUES (:Name, :Position, :Salary)';
FDQuery1.ParamByName('Name').AsString := '张三';
FDQuery1.ParamByName('Position').AsString := '软件工程师';
FDQuery1.ParamByName('Salary').AsFloat := 8500.50;
try
FDQuery1.ExecSQL;
ShowMessage('数据插入成功!');
// 插入后需要刷新查询才能看到新数据
FDQuery1.Close;
FDQuery1.Open;
except
on E: Exception do
ShowMessage('插入失败: ' + E.Message);
end;
更新数据
FDQuery1.SQL.Text := 'UPDATE Employees SET Salary = :NewSalary WHERE Name = :EmpName';
FDQuery1.ParamByName('NewSalary').AsFloat := 9000.00;
FDQuery1.ParamByName('EmpName').AsString := '张三';
try
FDQuery1.ExecSQL;
ShowMessage('数据更新成功!');
FDQuery1.Close;
FDQuery1.Open;
except
on E: Exception do
ShowMessage('更新失败: ' + E.Message);
end;
删除数据
FDQuery1.SQL.Text := 'DELETE FROM Employees WHERE Name = :EmpName';
FDQuery1.ParamByName('EmpName').AsString := '张三';
try
// 先检查是否存在,避免误删
FDQuery1.Close;
FDQuery1.SQL.Text := 'SELECT COUNT(*) FROM Employees WHERE Name = :EmpName';
FDQuery1.ParamByName('EmpName').AsString := '张三';
FDQuery1.Open;
if FDQuery1.Fields[0].AsInteger > 0 then
begin
FDQuery1.Close;
FDQuery1.SQL.Text := 'DELETE FROM Employees WHERE Name = :EmpName';
FDQuery1.ParamByName('EmpName').AsString := '张三';
FDQuery1.ExecSQL;
ShowMessage('数据删除成功!');
end
else
begin
ShowMessage('未找到名为 ' + '张三' + ' 的员工。');
end;
FDQuery1.Close;
FDQuery1.Open; // 刷新列表
except
on E: Exception do
ShowMessage('删除失败: ' + E.Message);
end;
第四部分:高级篇 - 数据绑定与用户界面
手动操作数据很繁琐,现在我们来利用 Delphi 的强大数据绑定功能,创建一个可视化的界面。
步骤 1: 添加 UI 组件
- 从
Standard页面拖拽一个TDataSource到窗体,重命名为dsEmployees。 - 从
Data Controls页面拖拽以下组件到窗体:TDBGrid: 用于以表格形式显示数据。TDBNavigator: 用于提供导航和编辑按钮(上一条、下一条、添加、删除等)。TDBEdit: 用于编辑单行数据。TDBComboBox: 用于下拉选择数据。
- 从
Standard页面拖拽几个TLabel用于提示。
步骤 2: 建立绑定关系
这是最关键的一步,在 Object Inspector 中设置以下属性:
-
选中
dsEmployees:DataSet属性设置为FDQuery1,这样dsEmployees就和我们的数据源关联起来了。
-
选中
DBGrid1:DataSource属性设置为dsEmployees。
-
选中
DBNavigator1:DataSource属性设置为dsEmployees。
-
选中
DBEdit1(用于编辑姓名):DataSource属性设置为dsEmployees。DataField属性设置为Name。
-
选中
DBComboBox1(用于编辑职位):DataSource属性设置为dsEmployees。DataField属性设置为Position。- 在
Items属性中,点击 按钮,添加几个职位选项,如 "经理", "软件工程师", "测试员"。
-
选中
DBEdit2(用于编辑薪水):DataSource属性设置为dsEmployees。DataField属性设置为Salary。
运行你的程序,奇迹发生了!FDConnection1 会自动连接,FDQuery1 会自动打开并加载数据,DBGrid1 会显示所有员工,DBNavigator1 的按钮(如添加、删除)可以正常工作,而 DBEdit 和 DBComboBox 会显示当前选中员工的信息。
当你修改 DBEdit 中的内容并移动到下一条记录时,数据会自动保存到数据库中(这通常由 FDQuery1 的 AutoCommit 或 FDConnection1 的 Transaction 控制)。
第五部分:实战篇 - 构建一个完整的 CRUD 应用
结合以上所有知识,我们可以构建一个功能完整的员工管理应用。
-
界面设计:
- 使用上述的
TDBGrid,TDBNavigator,TDBEdit等组件。 - 添加一个
TButton,Caption设为 "刷新数据"。 - 添加一个
TButton,Caption设为 "查询"。
- 使用上述的
-
代码逻辑:
-
窗体创建时 (
FormCreate):procedure TForm1.FormCreate(Sender: TObject); begin // 连接数据库 FDConnection1.Connected := True; // 加载数据 LoadEmployees; end; procedure TForm1.LoadEmployees; begin FDQuery1.Close; FDQuery1.SQL.Text := 'SELECT * FROM Employees ORDER BY ID'; FDQuery1.Open; end;
-
"刷新数据" 按钮点击事件:
procedure TForm1.btnRefreshClick(Sender: TObject); begin LoadEmployees; end;
-
"查询" 按钮点击事件 (按姓名查询):
procedure TForm1.btnSearchClick(Sender: TObject); begin FDQuery1.Close; FDQuery1.SQL.Text := 'SELECT * FROM Employees WHERE Name LIKE :NameParam ORDER BY ID'; FDQuery1.ParamByName('NameParam').AsString := '%' + edtSearchName.Text + '%'; FDQuery1.Open; end;
-
-
运行测试:
- 启动应用,所有员工显示在网格中。
- 使用
DBNavigator添加、删除、修改员工。 - 在查询框中输入员工姓名的一部分,点击 "查询" 按钮,网格会显示匹配的员工。
- 点击 "刷新数据" 按钮,会重新加载所有员工。
至此,你已经掌握了使用 Delphi 和 FireDAC 开发数据库应用的核心流程。
第六部分:学习资源与最佳实践
推荐资源
- 官方文档: Embarcadero 官网的 DocWiki 是最权威、最全面的资源,搜索 "FireDAC" 或 "dbExpress" 可以找到详细的指南和示例。
- Embarcadero 官方示例: Delphi 安装目录下有大量示例代码,特别是
FireDAC\Samples文件夹,包含了各种数据库和高级功能的演示。 - 书籍:
- 《Mastering Delphi》 by Marco Cantù (经典著作,涵盖所有版本)
- 寻找最新的 Delphi 数据库开发相关书籍。
- 社区与论坛:
- Embarcadero Community: https://community.embarcadero.com/ - 官方社区,有大量专家和开发者活跃。
- Stack Overflow: 标签
[delphi]和[fire-dac]。
最佳实践
- 始终使用参数化查询: 不要用字符串拼接来构建 SQL 语句,这不仅能防止 SQL 注入攻击,还能提高数据库引擎的 SQL 缓存效率。
- 坏:
FDQuery1.SQL.Text := 'SELECT * FROM Users WHERE Name = ''' + Edit1.Text + ''''; - 好:
FDQuery1.SQL.Text := 'SELECT * FROM Users WHERE Name = :Name'; FDQuery1.ParamByName('Name').AsString := Edit1.Text;
- 坏:
- 管理连接生命周期: 不要在程序启动时连接,在程序关闭时断开,在需要数据时连接,操作完成后及时断开或保持连接池状态,避免频繁地连接和断开。
- 使用事务: 对于一组需要作为一个原子单元执行的 SQL 操作(银行转账:扣款+存款),一定要使用
TFDTransaction,这能确保数据的一致性。FDTxn1.StartTransaction; try FDQuery1.ExecSQL('UPDATE Accounts SET Balance = Balance - 100 WHERE ID = 1'); FDQuery2.ExecSQL('UPDATE Accounts SET Balance = Balance + 100 WHERE ID = 2'); FDTxn1.Commit; // 全部成功,提交事务 except FDTxn1.Rollback; // 任何一步失败,回滚所有操作 raise; end; - 关注性能:
- 只查询你需要的字段 (
SELECT Field1, Field2 ...而不是SELECT *)。 - 为大型表添加适当的索引。
- 避免在循环中执行 SQL 语句,尽量批量处理。
- 只查询你需要的字段 (
- 错误处理: 始终将数据库操作(
Open,ExecSQL等)放在try...except块中,并向用户显示友好的错误信息,而不是让程序崩溃。
希望这份详细的教程能帮助你顺利开启 Delphi 数据库开发之旅!祝你编码愉快!
