
简介面向Delphi开发者的LiteSQL 2019 X64资源包适配Delphi 12.3环境是一款轻量级SQL查询构建器控件。它提供简洁明了的应用程序编程接口能够快速集成到Delphi项目中帮助开发者直观构建查询语句减少手写复杂结构化查询语言的时间同时提升代码的可读性与可维护性尤其适合需要高效处理数据库交互的视窗桌面应用开发场景。压缩包内共包含二百八十个文件整体大小约五十四兆字节主要文件类型包括dll动态链接库、rll本地化资源文件、tql查询脚本、exe可执行工具以及ini与config配置文件、mdf与ldf数据库文件等覆盖自动安装、运行查询、参数配置与测试数据库等完整环节。其中与微软SQL服务器相关的演示文件便于在本机环境验证控件功能但按照许可说明仅供测试使用用后应在规定时间内及时删除。已有二百一十八人学习下载可作为Delphi数据库开发中构建查询层的一手参考。1. LiteSQL-2019X64 到底装的是什么一块 2019 年的控件包在 Delphi 12.3 里怎么立起来接手一台新机器Delphi 12.3 装好老工程一编译就报 DCU not found。打开工程一看几百个窗口全挂在 LiteSQL 控件上底层是 SQLite 数据库。这个包是 2019 年那批包名后缀 X64当时在 Win32 下跑得顺顺当当换到 64 位编译环境第一关就卡在控件安装上。这篇文章就把这套流程完整拆一遍LiteSQL 是干什么的、为什么 2019 年的老包能装进 Delphi 12.3、X64 的库路径怎么配、连库建表和事务怎么写以及我从这个包上踩过的五个坑。适合正在维护老数据库工具、或者拿到一个新环境想把旧工程立起来的人。没有废话直接从选型逻辑开始。2. LiteSQL 选型逻辑SQLite 内核算什么2019 的老包为什么还能继续用2.1 LiteSQL 的本质一个控件壳加上一个 SQLite 内核LiteSQL 从名字就能看出路子轻量级 SQL 数据库访问控件。它本质上是个壳壳里套一个 SQLite 的 C 库壳外给 Delphi 程序员一组可视组件。SQLite 把整个数据库塞进一个 .db 文件无服务、零配置这对桌面工具类项目非常友好。而 LiteSQL 这类控件的价值是把 C API 里的 sqlite3_open、sqlite3_prepare、sqlite3_step 这些底层函数接出来变成设计期就能拖放的连接组件和查询组件。你在设计器里填属性运行期它替你拨底层 API。用习惯了 FireDAC 的人对这个套路不会陌生组件替你管句柄、管事务、管游标省掉大量重复的 Free 和 Close 代码。对老工程来说这套封装已经是事实标准界面层几十个窗口全在调用它这时候换底层实现是伤筋动骨的事。所以「用 LiteSQL」不是技术洁癖而是对既有代码资产的尊重。2.2 版本兼容的原理2019 不是障碍源码重新编译才是关键很多人第一反应是 2019 年的包装不进 12.3。这其实是个误区。Delphi 的包机制里.dcu 是带编译器版本标记的2019 年编译出来的 DCU 在 12.3 里直接引用确实会报错但控件包通常附带的是 .dpk 源码工程你在当前 IDE 里重新编译一遍产出的就是适配 12.3 的 DCU 和 BPL。所以老包能不能用不取决于年份取决于两件事包的接口有没有依赖已经移除的旧单元以及你有没有在 64 位平台下重新编译。LiteSQL-2019X64 这个后缀里X64 说明当年构建时就按 64 位目标走过一遭接口不大可能依赖已经废弃的东西。SQLite 的 C API 向后兼容性又出奇地好十几年没变过核心调用方式控件壳只要不瞎改封装搬家难度就低。我见过很多老外包卡住的原因几乎都是「拿 2019 年的 DCU 直接塞进 12.3」而不是「包本身有问题」。另外提醒一句网上搜到的教程有一半是 Lazarus 的 sqlite 组件安装方法Lazarus 和 Delphi 的包机制有差距.lpk 和 .dpk 是完全两套体系照搬会卡在奇怪的地方。2.3 和 FireDAC、裸调 sqlite3.dll 的差别对比项LiteSQL 控件包FireDAC裸调 sqlite3.dll封装层级可视组件设计期配置官方数据访问框架功能全C API全靠手写部署形态编译进 EXE 或带 BPL带官方驱动体积偏大带一个 DLL最轻学习成本低拖组件写属性即可中高概念多配置项多高句柄和回调都要自己管适用场景老工程维护、轻量桌面库新项目、多数据库适配嵌入式、性能敏感项目迁移成本保持原样零迁移需要重写数据访问层需要重写数据访问层这条路的典型组合是LiteSQL 负责把业务数据沉淀到 SQLite导出阶段再交给 Excel 报表模块做格式化输出各司其职。如果是从零起新项目我会考虑 FireDAC但如果手头全是 LiteSQL 组件就别在这个时点翻新到 FireDAC界面层、业务层、数据层全部重写一遍成本是控件的几十倍。控件老不代表要立刻推翻先把它跑起来这是性价比最高的选择。3. 装进 Delphi 12.3包文件分工、X64 编译顺序与 Library Path 配置3.1 解压后先认文件.dpk、.dcu、.bpl 各干什么拿到压缩包解压后先别急着打开 Delphi先把目录结构看明白。这些文件的角色区分清楚了后面装包基本不会翻车。文件类型角色定位需要做什么.dpk包源码工程编译入口用 Delphi 12.3 打开重新编译.dcu编译产物带版本标记的中间代码由 .dpk 编译生成千万不要手动拷贝别人的.bpl运行期/设计期包IDE 加载的二进制编译后在 Install Packages 里注册.res资源文件包图标等一般不用管编译时自动引用Demo示例工程强烈建议先读能少踩一半坑最容易混的是运行期包和设计期包的区分。运行期包是给编译后的程序用的设计期包是给 IDE 在组件面板上显示用的。设计期包一般名字里带个 D 后缀这个 D 就是 Design 的意思。装的时候只装了运行期包组件面板上是看不见控件的这个坑下面第 5 章专门讲。3.2 编译顺序先运行期包再设计期包64 位平台编译一次编译顺序有讲究先编译运行期包再编译设计期包因为设计期包依赖运行期包的构建结果。在 IDE 里打开 .dpk 后先看 Project Manager 里的 Platform 是不是 Win64。Delphi 12.3 新建包工程时默认可能是 Win32需要手动切到 Win64。常用做法是在 IDE 里操作右键工程节点选 Build编译一次。也可以用命令行批量处理特别是要同时装多个 Delphi 版本的时候msbuild LiteSQL.dpk /p:PlatformWin64 /p:ConfigRelease /t:Build;Install/p:PlatformWin64对应 IDE 里的平台切换告诉编译器按 64 位目标产出 DCU/p:ConfigRelease走 Release 配置Debug 配置也能编但发布用 Release 更干净/t:Build;Install是 msbuild 的目标列表Build 编译Install 把包注册进当前 IDE。LiteSQL.dpk换成你实际包里的文件名有的包拆成多个 dpk那就把每个都 Build 一次再 Install。我一般在 IDE 里手工编译因为能看到哪个单元先报错排查起来更直接。命令行适合机器环境固定、要反复重装的情况。编译期间报错先别慌看是哪个单元的问题多半是源码里引用了缺失的旧单元把那条 uses 删掉或替换再编。3.3 Library Path装了为什么还报 File not found编译成功只是第一步IDE 还得能找到这些 .dcu否则工程一编译照样报 File not found。这里必须配 Library Path。打开 Tools Options Language Delphi Library左侧 Platform 列表里先选 Win64把编译输出的目录加进 Library Path。注意顺序Win32 和 Win64 的 Library Path 是分开维护的很多人只配了 Win32切到 Win64 编译立刻翻车。建议目录结构长这样角色建议路径包的根目录D:\Components\LiteSQL-2019X64\源码搜索目录根目录\SourceWin64 DCU 输出根目录\Win64\ReleaseWin32 DCU 输出根目录\Win32\Release提示Win32 和 Win64 的 Library Path 在 IDE 里分别维护。给 Win64 加完路径后顺手把 Platform 切回 Win32 再检查一次两套路径各配各的。Delphi 12.3 之后的版本如果要把这套流程照搬菜单路径基本一致只是默认库路径不同。核心原则就一句话哪个平台编译就给哪个平台配上对应的 DCU 目录。3.4 验证安装结果新建一个空工程试跑配完路径后验证安装是否成功别急着写业务代码新建一个 VCL 工程在组件面板里找 LiteSQL 页签。找不到就回头检查设计期包有没有 Install找到了就拖一个连接组件到窗体编译运行。这里有个技巧先让一个空壳工程跑通确认 IDE 和程序都不报警再动老工程这是成本最低的验证方式。空壳能跑老工程报错就只可能是老工程自身的问题排查范围一下子缩小很多。4. 第一张表连接串、参数化写入与事务批量导入的完整代码4.1 连接一个 SQLite 数据库文件下面是这块控件包最常见的调用范式。类名我用 TSQLiteConnection 和 TSQLiteQuery 来写这是按 SQLite 名词体系的默认命名习惯。你拆包以后以包内 Demo 里的实际类名为准有的包写作 TxxxDatabase、TxxxQuery把前缀换掉逻辑完全不变。// 在窗体上放一个 TSQLiteConnection或者代码里动态创建 LiteConnection : TSQLiteConnection.Create(nil); try LiteConnection.Database : D:\data\app.db; LiteConnection.Connect; // 连接成功后可以在这里执行初始化脚本 finally // 注意不是在 finally 里立刻释放 end;先解释逻辑连接组件负责生命周期Database 属性指定数据库文件路径Connect 方法建立物理连接。如果文件不存在SQLite 会尝试自动创建前提是所在的目录有写权限。这里刻意不在 finally 里释放连接是因为连接应该跟随窗体生命周期在 FormDestroy 里统一关闭释放频繁开关连接对 SQLite 来说没有必要。再说几个参数Database 是主库文件路径SQLite 还有一个日志库概念控件包的属性名可能叫 Journal 或直接走默认配置默认连接状态下多线程同时写会有锁竞争如果程序里是多线程写入需要查控件包是否暴露了 busy_timeout 和 预写日志相关的参数。这块老控件实现参差不齐实用做法是启动时先用单线程把结构建好再放开业务线程。4.2 建表执行 DDL 的方式LiteQuery : TSQLiteQuery.Create(nil); try LiteQuery.Connection : LiteConnection; LiteQuery.SQL.Text : CREATE TABLE IF NOT EXISTS record ( id INTEGER PRIMARY KEY AUTOINCREMENT, device_no TEXT NOT NULL, batch TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); LiteQuery.ExecSQL; finally LiteQuery.Free; end;DDL 语句没有返回集所以走 ExecSQL 而不是 Open。IF NOT EXISTS 是 SQLite 的容错写法老工程升级时反复执行建表脚本不会报错。字段类型这里用 TEXT 和 DATETIMESQLite 是动态类型系统DATETIME 实际上是文本存储格式由 DEFAULT CURRENT_TIMESTAMP 生成。如果控件包的 Execute 方法名称不同在 Demo 里搜一下建表示例就能找到对应写法。4.3 参数化写入别用字符串拼接LiteQuery.SQL.Text : INSERT INTO record(device_no, batch) VALUES(:device_no, :batch); LiteQuery.ParamByName(device_no).AsString : edtDevice.Text; LiteQuery.ParamByName(batch).AsString : cmbBatch.Text; LiteQuery.ExecSQL;参数化写入在这个场景下有两个直接好处。一是防注入设备编号这类业务字段如果直接拼进 SQL遇到特殊字符就是一条脏数据参数绑定后输入内容只当值处理不参与语句解析。二是类型匹配AsString 明确告诉绑定层按字符串写入避免文本字段被错误转成数字。ParamByName 找不到参数时会抛异常如果你用了动态 SQL 拼了不同的查询条件执行前先检查参数名是否和 SQL 文里的占位符一一对应。4.4 事务与批量导入一个数量级的性能差距LiteConnection.StartTransaction; try for i : 0 to dataList.Count - 1 do begin LiteQuery.SQL.Text : INSERT INTO record(device_no, batch) VALUES(:device_no, :batch); LiteQuery.ParamByName(device_no).AsString : dataList[i].DeviceNo; LiteQuery.ParamByName(batch).AsString : dataList[i].Batch; LiteQuery.ExecSQL; end; LiteConnection.Commit; except LiteConnection.Rollback; raise; end;逐条自动提交和事务批量写的差距在数据量大时是数量级的。原因是 SQLite 每条 commit 都要做磁盘同步事务把很多次磁盘同步压成一次我这边同样的万行导入开事务比逐条自动提交快一个数量级是常见情况。有几个细节Commit 成功后要把状态清掉Rollback 只处理异常分支原异常通过 raise 重新抛出让上层知道这批次作废了如果循环里某条数据本身业务校验不合法要先过滤掉别让一条坏数据把整个批次回滚。SQLite 不支持嵌套事务外层事务未提交时内层 Begin 会直接失败如果你的控件封装了 NestedTransaction它多半是用 SAVEPOINT 模拟的底层不是真事务。4.5 读数据遍历结果集LiteQuery.SQL.Text : SELECT id, device_no, created_at FROM record WHERE batch :batch; LiteQuery.ParamByName(batch).AsString : B2025001; LiteQuery.Open; try while not LiteQuery.Eof do begin id : LiteQuery.FieldByName(id).AsInteger; deviceNo : LiteQuery.FieldByName(device_no).AsString; // 处理当前行 LiteQuery.Next; end; finally LiteQuery.Close; end;Open 之后组件进入数据集状态Eof 表示是否已经越过最后一行Next 移动到下一行。注意 FieldByName 每次调用都要做字段名查找循环里大量行时可以先用 Lookup 缓存字段引用能省不少字符串比较。遍历过程中不要对正在读取的表做结构变更SQLite 的读游标会被后续的写操作干扰轻则返回旧数据重查重则直接报 database is locked。5. 避坑记录X64 控件安装最容易翻车的五个细节5.1 msxmldom.dcu not found升级 IDE 后的第一个报错现象老工程在 Delphi 12.3 下编译报 File not found: msxmldom.dcu。原因uses 里还挂着旧式 XML 单元Delphi 新版本把 XML 相关单元挪到了命名空间下老单元名还在但对应的 DCU 没跟着新 IDE 一起发布。解决先在 uses 里定位是哪个单元引用了 msxmldom然后把它替换成新写法通常是 Xml.XMLDoc如果只是传递引用直接把这条 uses 删掉即可再重新编译。这个报错和 LiteSQL 本身没关系但老工程升级时几乎必定碰到因为界面层经常会在 XML 工具和数据库工具之间做数据交换。5.2 组件面板里找不到 LiteSQL只装了运行期包现象BPL 编译成功Install Packages 里能看到包名组件面板里就是没有 LiteSQL 页签。原因装进去的是运行期包设计期包没有编译或者没有 Install。设计期包才负责向 IDE 注册组件运行期包只提供底层功能。解决把名字里带 D 后缀的设计期 .dpk 也编译一次然后在 IDE 的 Install Packages 对话框里点 Add选中生成的设计期 .bpl确认后组件面板刷新就有页签了。判断包是运行期还是设计期看它里面有没有 Register 函数设计期包都会有 Register 来登记组件类。5.3 Cannot load packageBPL 从别的机器拷贝过来就是埋雷现象运行时报 Cannot load package xxx.bpl或者包加载一半 IDE 直接提示错误。原因最常见的是图省事把另一台机器上编译好的 BPL 直接拷到当前环境。BPL 内部记录着 IDE 架构和编译环境信息换机器换版本大概率不兼容。很多人觉得装控件是玄学其实八成翻车在这里。解决卸载掉可疑的包在本地把 .dpk 重新 Build 一遍再用新产出的 BPL 安装。记住一个原则BPL 永远在目标机器上现编译绝不跨机器拷贝。我见过太多拿 U 盘拷 BPL 的同事最后全回来重新走编译流程。5.4 程序首次运行就崩32 位工程配了 64 位控件现象控件安装顺利组件也能拖出来程序一运行就 Access Violation毫无预兆。原因包后缀 X64 意味着按 64 位构建的但工程本身还是 Win32 平台。运行时控件壳调用 64 位的 SQLite 实现32 位进程去加载 64 位代码不做任何提示直接崩。解决右键 Project Manager 里的工程节点把 Target Platforms 加 Win64 并激活重新编译整个工程让所有引用全部按 64 位走。反过来一样如果团队的部署机器只支持 32 位就不要用 X64 包找源码在 Win32 下重新编一套。32/64 混着用是这类控件最容易踩的坑没有之一。5.5 中文路径下的数据库打不开编码不一致现象数据库放在 D:\数据\app.db连接时报错或者能连上但写入失败。原因老控件内部处理路径用的是 ANSI 编码Delphi 12.3 默认字符串是 UTF-8 编码两者在中文路径上对不上。解决连接之前先把路径做一次编码转换转成控件期望的目标编码再赋给 Database 属性。更省事的做法是约定俗成工具类程序的数据库文件放纯英文路径比如 D:\AppData\app.db彻底绕开这个雷。这是条血泪经验尤其部署到政府单位或老企业环境时中文用户名、中文桌面路径到处都是。6. 收进工程模板数据访问壳、启动自检与备份的日常工作流6.1 把连接生命周期收进一个类每次打开都写一遍 Try Create 很啰嗦我会在工程模板里放一个连接外壳type TLocalDB class private FConn: TSQLiteConnection; public constructor Create(const ADbPath: string); destructor Destroy; override; procedure InitSchema; function Query(const ASQL: string): TSQLiteQuery; property Conn: TSQLiteConnection read FConn; end;InitSchema 里放 CREATE TABLE IF NOT EXISTS 那段脚本程序启动时调用一次保证新机器上拉起就能用。Query 方法返回一个绑定了当前连接的查询组件调用方用完负责 Free。这个外壳的收益是界面层不感知连接细节业务代码里只写 SQL 和数据处理。6.2 启动自检别省数据库文件损坏是个低概率但高杀伤的事件。启动时执行一次完整性检查花费极小PRAGMA integrity_check;返回 ok 表示库文件结构完整。如果返回乱码或错误码程序直接弹窗提示重新初始化数据而不是带着坏库继续跑。这个自检放在 TLocalDB.InitSchema 之前执行我这几年的习惯是永远先检查再建表顺序反了会让已有数据被覆盖掉。6.3 备份用 VACUUM INTO我一般每周自动备份一次 SQLite 库。最顺手的方式是 VACUUM INTO 语法它把当前库压缩成一个紧凑副本顺带回收空闲页VACUUM INTO D:\backup\app_20250701.db;如果控件包内置的 SQLite 内核版本较老不支持这个语法退而求其次就是文件复制但复制前先做一次 checkpoint 把日志落盘。从那以后我每换一台机器、每升一次 Delphi 版本都强制把这件事走一遍64 位平台编译、库路径配好、空壳工程验证、启动自检通过然后才动手写业务。这个顺序省掉的排查时间远比安装那几分钟多。希望帮到你。本文还有配套的精品资源点击获取