
简介Absolute Database v7.93 源代码包面向使用 Delphi 4 至 11 的开发者与数据库组件研究者提供一套可研读、编译和定制的面向对象关系型数据库引擎实现用于理解事务处理、缓存管理、权限加密、备份恢复及多用户并发等核心机制。压缩包共 756 个文件约 18.9MB包含 sql 脚本、hpp/c/pas 源文件、dcu 编译单元、res/dfm 窗体资源、dpk/bdsproj 工程文件以及 chm/txt 文档覆盖源码、工程配置、示例与说明便于按模块检索。已有 446 人学习说明其在 Delphi 数据库开发社区中具有一定参考价值。读者可据此追踪引擎内部结构结合 Delphi 11 Alexandria 的组件集成方式做性能分析与二次开发也可参考其数据库迁移、并发访问和多平台兼容设计为维护旧项目或构建定制数据库方案提供可复用的代码基础。1. 先选对目录Absolute_Database_v7.93_sources_for_D4-11 不是一套包通吃上个月帮人远程看一个老项目他在 Delphi 11 里双击了一个AbsDB.dpk点 InstallIDE 直接弹“Cannot load package”组件面板一片空白回头还顺手把 IDE 的包列表搞乱了。问题不在他操作而在于Absolute_Database_v7.93_sources_for_D4-11这套源码包横跨 Delphi 4 到 Delphi 11 十几个版本目录里躺着的是多份工程文件你却只能装其中一份。数据库组件这种带设计期包的东西装错的代价不小——轻则组件面板多出两页重复项重则每次打开 IDE 都提示包加载失败。这篇笔记写的是我自己在几个版本上装这套源码的完整路径先认目录再编运行期包再装设计期包最后拿一个真实可读写的库文件验证适合正在给老项目补数据库层、或者想把 BDE 依赖彻底摘掉的开发者。2. 装前准备Delphi 版本、平台与输出目录的一次性核对动手之前先把三件事定死能省掉后面八成的返工。这套包是源码版不是二进制 dcu 版意味着所有单元都要用你本机的编译器重新生成一遍。源码版的好处也在这里只要源码里有对应的条件编译分支你的编译器就能编出匹配当前 RTL 的 dcu坏处是它对路径和输出目录比二进制包敏感得多路径一乱IDE 就会去别的地方找同名单元然后报一堆看不懂的错。下面三节是我每次装之前固定要走一遍的核对流程。2.1 确认 IDE 版本号与包目录的对应关系解压后你会看到类似packages、source或sources这样的顶层结构packages下面按版本分文件夹常见命名是D7、D2007、D2010、DXE2、DXE8、D10_2、D10_4、D11这一类。名字不统一很正常老包跨的年代太长作者换过好几轮命名习惯。判断该用哪个别看文件夹名看 IDE 自己的版本标识Delphi 4~7 是dcc32的老世代工程文件只有.dpk和.bpgDelphi 2007 之后开始有.dproj和.groupprojDelphi XE2 起才有 Win64 平台选项Delphi 2009 起字符串变 Unicode源码里必然靠{$IFDEF UNICODE}分叉。对照表可以这么记IDE 世代工程形态关键差异Delphi 4~7.dpk.bpg无 Unicode包只编 Win32Delphi 2005~2007.dpk.dproj混用开始有.dproj仍需核对Delphi 2009~XE.dprojUNICODE已定义字符串全部变了Delphi XE2~XE8.dproj 平台节点出现 Win64需要分别编包Delphi 10.x~11.dproj.groupproj平台配置写在工程里别手改提示拿不准就打开 IDE 的 Help About把版本号记下来再去packages下找最接近的那一层。宁可装低一档的目录试编也别把 D7 的 dcu 硬塞给 D11。这里最容易翻车的是“降档使用”。有人图省事拿 D2010 的目录在 XE2 里打开编译能过装上去组件也能出现但一放到项目里就报Unsatisfied forward or external declaration——因为源码里的条件分支根本没覆盖到你的编译器版本某些方法只有声明没有实现。这种错不会在装包时报只会在你正式用的时候炸排查成本翻倍。2.2 规划 BPL/DCP/DCU 输出目录三个路径别混Delphi 装包涉及三类产物很多人把它们混在一个目录里然后互相覆盖BPL运行期包和设计期包的二进制包文件运行时被 IDE 或 exe 加载DCP包编译时生成的符号信息供下一个包引用DCU单元编译产物供普通工程直接引用。源码包编译时设计期包dcl*依赖运行期包*编译器要通过 DCP 找到运行期包的接口。如果你把两个包的输出路径设成不一样或者用了 IDE 默认的“与工程同目录”那dclAbsDB编译时找不到AbsDB的 DCP就会退回去找源码单元重新编一份结果是同一批单元在内存里有两份装完组件能用但调试时断点乱跳、异常栈错位。我一般固定这么规划D:\DelphiLib\AbsDB793\bpl\Win32 - BPL 输出 D:\DelphiLib\AbsDB793\dcp\Win32 - DCP 输出 D:\DelphiLib\AbsDB793\dcu\Win32 - DCU 输出在 IDE 里对应 Project Options Delphi Compiler 下的Package output directory、DCP output directory、Unit output directory三项两个包必须填同一套。命令行编译时对应/LE、/LN、/NU这类开关用 msbuild 的话是/p:DCC_BplOutput、/p:DCC_DcpOutput、/p:DCC_DcuOutput。注意路径里不要有中文和空格Program Files这种带空格的路径也别用。Delphi 的包编译器对空格的处理在不同版本间不一致老版本会截断参数。2.3 备份与还原点装坏了怎么退回装包这件事血泪经验是“先想好怎么退”。IDE 的已安装包列表存在注册表里HKCU\Software\Embarcadero\BDS\版本\Known Packages这类位置手工删容易删漏。我的做法是装之前先导一份# 以管理员身份打开 cmd导出已安装包列表出问题直接还原 reg export HKCU\Software\Embarcadero\BDS\22.0\Known Packages D:\backup\knownpackages_d11.reg /y这条命令把当前 IDE 认识的包清单整个存下来22.0是 Delphi 11 的内部版本号10.4 是21.010.3 是20.0按你的实际版本改。出问题时双击.reg还原重启 IDE组件面板就回到装之前的状态。另外源码包解压后建议先整个复制一份到工作目录再动。有人直接在解压目录里编译编完发现目录被生成的 dcu、dcp 塞满想重新来一遍都分不清哪个是原始文件。我一般保留一份_orig副本编译只在工作副本里做。3. 编译运行期包与安装设计期包从 AbsDB.dpk 到 dclAbsDB这套包的安装顺序是硬性的先编运行期包再装设计期包。运行期包提供组件类的实现设计期包只负责把组件注册到 IDE 的工具面板上。顺序反了设计期包编译时会找不到运行期包的接口然后编译器会自作聪明地去源码目录重新编一份你得到的是一个“假装装好了”的 IDE——组件在面板上但拖到窗体上就报错。3.1 先编运行期包别急着点 Install打开对应版本目录找到不含dcl前缀的那个包工程名字通常是AbsDB.dpk或带版本后缀的形式。以 Delphi 11 为例先确认工程里Requires段引用的都是 RTL/VCL 的标准包没有指向别的第三方包。然后执行编译# 在 Delphi 安装目录的 bin 下执行路径换成你自己的工程路径 msbuild D:\DelphiLib\AbsDB793\packages\D11\AbsDB.dproj ^ /t:Build /p:PlatformWin32 /p:ConfigRelease ^ /p:DCC_BplOutputD:\DelphiLib\AbsDB793\bpl\Win32 ^ /p:DCC_DcpOutputD:\DelphiLib\AbsDB793\dcp\Win32 ^ /p:DCC_DcuOutputD:\DelphiLib\AbsDB793\dcu\Win32/t:Build是完整重建不是增量编译第一次装包必须用它否则残留的旧 dcu 会让编译器跳过实际编译。/p:PlatformWin32明确平台别指望默认值——有些工程的默认平台是空的msbuild 会拿第一个可用平台凑数。三个输出目录参数就是上一节规划的那三个保持一致。命令行编不过也别慌回到 IDE 里打开同一个.dprojProject Build 一次看 Messages 窗口第一条错误。编译失败通常是源码里的条件编译没覆盖到你的版本比如某个方法在{$IFDEF VER350}分支里才有实现。这种情况正确做法是往上找一档能编过的目录而不是去改源码——改源码会在下次升级时全部丢失。编完检查一下输出目录应该有.bpl和一批.dcudcp目录下有.dcp。三个目录都有东西才算这一步过关。3.2 安装设计期包与组件面板落地运行期包编译通过后打开同目录下的dclAbsDB.dpk或对应名字的设计期包确认它的Requires里已经包含刚编好的运行期包然后右键 Install。IDE 会先编译再注册成功后组件面板会多出一个页签里面是数据库、数据集、查询这几类组件。如果 Install 之后面板没变化去 Component Install Packages 看列表里有没有新条目勾选状态对不对。还有一种情况是面板出现了但组件是灰的那基本是运行期包的 BPL 没被 IDE 加载——检查 IDE 的环境变量 PATH 里有没有包含你的bpl\Win32目录没有就加上重启 IDE。64 位项目要特别注意设计期包只需要 Win32 一份因为 IDE 自己是 32 位进程但运行期包要按你的目标平台分别编。如果项目要出 Win64就在同一个工程上切平台再 Build 一次输出到bpl\Win64然后确认库路径里 64 位那一份指向正确。3.3 库路径Library Path / Browsing Path怎么填这一步是最容易留下隐患的地方。很多人为了“方便”直接把源码目录加进 Library Path结果项目编译时用的是源码单元跟包里的 dcu 版本不一致运行期出现莫名其妙的访问违例。正确的填法是Library Path只加dcu\Win32或 Win64不加源码目录Browsing Path可以加源码目录它的作用只是让 IDE 的代码跳转能找到实现不参与编译Debug DCU Path保持默认别指到第三方目录去。在 IDE 里对应 Tools Options Language Delphi Library平台下拉框选 Win32 和 Win64 分别配一遍。这两个平台的路径是分开存的很多人只配了 Win32切到 64 位就报找不到单元。提示配置完路径后把项目里所有*.dcu、*.identcache、__history之类的中间产物清掉再编译一次。Delphi 的增量编译对路径变更不敏感不清缓存你会以为路径没生效。4. 在项目里配置数据库连接TABSDatabase 参数逐个说清包装好只是环境通了真正落地是在项目里把一个库文件跑起来。这套组件的核心是三个东西数据库连接、表、查询。它走的是单文件嵌入式路子不需要装数据库服务也不需要 BDE 或 ADO 那套驱动层这对老项目迁移特别友好——原来靠 BDE 别名指向一堆配置现在一个文件路径就完事。下面按我实际配的顺序写。4.1 DatabaseFileName、Password 与只读/独占选项连接对象上有几个属性是必须先定的。DatabaseFileName指向库文件路径建议用相对路径配合ExtractFilePath(ParamStr(0))拼出来这样发布时整个目录拷走就能跑// 连接对象的最小配置放在窗体创建或数据模块 OnCreate 里 var DbDir: string; begin DbDir : ExtractFilePath(ParamStr(0)); // 以 exe 所在目录为基准 ABSDatabase1.DatabaseFileName : DbDir data\app.abs; ABSDatabase1.Password : ; // 未加密库留空加密库填实际口令 ABSDatabase1.ReadOnly : False; // 只读部署时置 True可避免多进程写冲突 ABSDatabase1.LoginPrompt : False; // 无人值守程序必须关掉否则弹框卡死 ABSDatabase1.Open; end;ExtractFilePath(ParamStr(0))保证在任何工作目录下启动都能找到库文件这是踩过坑之后的固定写法——早期我用相对路径data\app.abs从 IDE 里跑没问题一做成快捷方式启动就报文件不存在。LoginPrompt一定要关服务型程序或计划任务里没人给你点确定弹框会让进程挂在那儿。ReadOnly在只读部署场景建议打开多进程同时写同一个库文件时能少一类锁冲突。加密相关的属性以你手里AbsDB单元的接口声明为准版本之间枚举名有差异。常见做法是先设口令再建库建完的库后续每次打开都要给同样的口令口令错了报的是打开失败而不是解密失败别被错误信息误导。4.2 TABSTable 与 TABSQuery 的最小可用配置连接建好之后取数据有两条路TABSTable适合直接绑到网格上做增删改TABSQuery适合带条件查询。两者都通过Database属性挂到连接对象上。// 表对象绑定连接、指定表名打开即可编辑 ABSTable1.Database : ABSDatabase1; ABSTable1.TableName : customer; ABSTable1.Open; // 查询对象SQL 走 TStrings参数用 Params 传值 ABSQuery1.Database : ABSDatabase1; ABSQuery1.SQL.Clear; ABSQuery1.SQL.Add(select id, name, amount from customer where amount :minAmount); ABSQuery1.Params.ParamByName(minAmount).AsFloat : 1000; ABSQuery1.Open;Database属性是必须显式赋的即使在数据模块里只放了一个连接对象。有人指望“自动找同名的连接”在这套组件上不成立漏赋就是打开时报“未指定数据库”。参数化查询别用字符串拼接Params传值既避免引号转义问题也省得被单引号里带特殊字符的数据坑到。Open和ExecSQL的区别要分清select走Openinsert/update/delete走ExecSQL用错了前者不返回结果、后者不产生数据集都不报错但结果不对。4.3 免 BDE 发布与运行期自动建库源码版的最大价值在这整个数据库引擎编进 exe发布时不需要额外注册任何组件、不需要在客户机上装 BDE、不需要配别名。我在一个老系统迁移里就是靠这个把部署步骤从“装 BDE 配别名 注册驱动”压到“拷一个目录”。首次运行自动建库也是常见需求写法上就是先判断文件存在再建库建表// 首次启动时自动建库并建表避免手工准备空库 if not FileExists(ABSDatabase1.DatabaseFileName) then begin ForceDirectories(ExtractFileDir(ABSDatabase1.DatabaseFileName)); ABSDatabase1.CreateDatabase; // 建空库具体方法名以 AbsDB 单元为准 ABSDatabase1.Open; ABSDatabase1.ExecSQL(create table customer (id integer, name varchar(64), amount numeric(12,2))); end else ABSDatabase1.Open;ForceDirectories那行别省客户机上data目录通常不存在直接建库会失败。CreateDatabase这类建库入口在不同版本里名字可能不同编译一下就知道别照抄。建表语句尽量用最保守的类型varchar、integer、numeric这几个在跨版本时兼容性最好日期类型各版本处理有差异能存字符串就别硬用日期类型。注意库文件被一个进程打开时另一个进程的写操作可能失败。多实例部署时要么加锁机制要么在ReadOnly模式下分发只读副本。5. 避坑与排查Absolute Database v7.93 装完不能用的 5 个现场下面五条是我在不同机器、不同 Delphi 版本上真实撞到过的每条都按现象、原因、解决写。装包失败的时候先对照这套清单看一遍能省掉大量试错。5.1 安装设计期包报找不到运行期包现象右键dclAbsDB点 Install编译输出里第一行就是找不到AbsDB相关单元或包或者提示某个包“must be recompiled”。原因运行期包没编或者编了但输出目录和设计期包期望的 DCP 路径不一致。Delphi 找包依赖只认 DCP 路径不认源码路径。解决回到运行期包工程确认三个输出目录和设计期包填的完全一致Build 一次确认dcp目录下有对应文件再回去 Install。如果还是不行检查设计期包的Requires里那一行写的包名和你实际编出来的.bpl文件名是否一致——大小写不敏感但拼写必须对。5.2 组件面板出现重复页签或组件变灰现象装完发现工具面板里同一个组件出现两遍或者页签在但组件图标是灰的拖不动。原因之前装过别的版本或别的副本旧的 BPL 还留在 IDE 的已安装列表里。IDE 启动时会把列表里的包全加载一遍同名包加载两次就出现重复注册。解决Component Install Packages 里把所有跟这套组件相关的条目先 Remove重启 IDE再装一次。如果 Remove 后还复现用 2.3 节导出的注册表备份还原彻底清净之后再装。别手动去删 BPL 文件删了列表项还在下次启动还是报加载失败。5.3 切到 64 位平台后编译报单元找不到现象Win32 编译一切正常切到 Win64 就报找不到单元或者链接期报一堆未解析符号。原因只编了 Win32 的运行期包Library Path的 Win64 那一栏是空的或者还指向 Win32 的 dcu 目录。Delphi 的库路径按平台分开存很多人只配了一遍。解决在 Tools Options Library 里把平台切到 Win64把dcu\Win64加进去运行期包工程切到 Win64 平台再 Build 一次BPL 也要单独输出。设计期包不需要 64 位版本装 Win32 那份就够 IDE 用。5.4 项目编译时出现重复单元警告现象编译项目时提示某个单元“is also defined in...”或者断点打不上、异常栈里的行号对不上。原因源码目录被加进了 Library Path项目编译时优先用了源码单元自己编了一份跟包里的 dcu 形成两份实现。IDE 调试器加载的符号和实际运行的代码不是同一份。解决从 Library Path 里删掉源码目录只保留dcu输出目录需要看源码就把源码目录加到 Browsing Path。改完清掉项目里的*.dcu和*.identcache重新编译。5.5 升级 IDE 小版本后组件全部消失现象IDE 打了补丁或者小版本升级打开项目发现组件面板上的数据库页签没了项目里的组件变成红叉。原因IDE 升级会重建包缓存旧 BPL 跟新 RTL 的二进制接口不匹配加载失败后 IDE 直接把条目禁用了。解决不用重装整套把运行期包和设计期包按 3.1、3.2 的流程重新 Build Install 一遍就行。源码版的好处就在这里——重新编一次就对齐了二进制版遇到这种情况只能等厂商发新包。这也是我坚持用 sources 版的原因之一。6. 装完怎么验证跑通一个建库、写、读、关、再开的闭环组件装上了不等于环境能用我见过太多“面板上有图标、拖到窗体就报错”的情况。验证别只看能不能拖组件要走一个完整闭环建库、建表、写一条、读回来、关掉、重新打开再读一次。最后一步最关键很多问题只在第二次打开时才暴露。我一般新建一个空白 VCL 工程放一个连接对象、一个表对象窗体上扔一个按钮代码写成这样procedure TForm1.Button1Click(Sender: TObject); var DbFile: string; begin DbFile : ExtractFilePath(ParamStr(0)) verify.abs; if FileExists(DbFile) then DeleteFile(DbFile); // 每次验证从干净状态开始 ABSDatabase1.DatabaseFileName : DbFile; ABSDatabase1.LoginPrompt : False; ABSDatabase1.CreateDatabase; // 建库入口名以 AbsDB 单元为准 ABSDatabase1.Open; ABSDatabase1.ExecSQL(create table t1 (id integer, name varchar(32))); ABSDatabase1.ExecSQL(insert into t1 values (1, hello)); ABSDatabase1.Close; // 第一次关闭释放文件句柄 ABSDatabase1.Open; // 关键重新打开再读 ABSTable1.Database : ABSDatabase1; ABSTable1.TableName : t1; ABSTable1.Open; ShowMessage(ABSTable1.FieldByName(name).AsString); // 期望输出 hello ABSTable1.Close; ABSDatabase1.Close; end;每一步的检查点是这样的验证环节期望结果失败通常说明CreateDatabase目录下出现.abs文件方法名不对或目录无写权限Open 首次无异常口令错、路径错、BPL 版本不匹配create table无异常SQL 方言差异换类型试insert无异常表名拼写或字段数不匹配Close 后再 Open无异常文件句柄没释放多见于异常路径第二次读取拿到 hello打包进 exe 的单元和 BPL 不一致第二次Open那步是我特意加的。早期我不加这一步装完跑通了就交付结果客户机上程序退出再启动报“文件被占用”回头查了半天才发现是异常分支里没调Close句柄留着。从那以后我每次装这类数据库组件都强制走一遍“建库—写—读—关—再开”的循环哪怕只是给老项目补一个连接。跑通这一圈才算真的装好了。希望帮到你。本文还有配套的精品资源点击获取