ZeosDBO 6.0.12源码编译与TZConnection数据库连接实战
简介ZeosDBO 6.0.12最新稳定版源码包面向使用Delphi、C Builder、Kylix等Borland系开发工具的数据库应用开发者旨在提供跨数据库统一访问的原生数据集与组件覆盖MySQL、MSSQL、InterBase、Firebird、Sybase、PostgreSQL同时内置正则表达式与SQL解析对象可简化多数据库接入与查询处理流程。压缩包共包含387个文件其中92个pas源码为核心另有dpk/bpg工程文件、cfg/dof配置、res资源、cpp及bpk等Borland多语言工程支持文件整体仅1.19MB结构紧凑、便于快速获取与编译集成。目前已有267人学习下载。这套源码适合需要深入定制数据库组件或研究ZeosLib内部机制的中高级开发者拿到即可查看完整的单元源码、工程组定义与资源文件有助于理解其底层封装逻辑并可直接嵌入自身数据库中间件或应用框架中使用。1. zeosdbo-6.0.12 最新稳定版源码数据库组件包源码的打开方式如果你在 Delphi 或 Lazarus 里写桌面数据库程序多半听过 TZConnection 这个名字。zeosdbo-6.0.12 最新稳定版源码就是这套开源数据库组件库的完整源码包。它不是一个能双击安装的 exe而是一套需要你亲手编译进 IDE 的工程源码也正因为如此MySQL、PostgreSQL、Firebird、SQLite 这些数据库的连接逻辑都摊在你面前出了问题能直接进协议层查而不是对着黑匣子瞎猜。适合谁打算长期做跨平台数据库客户端、受够了第三方数据库中间件、或者想在框架里定制自己数据库驱动的开发者这份源码值得你完整下载并亲手编译一遍。2. 源码目录结构把 ZeosDBO 的分层协议摊开看拿到源码包后我习惯先花十几分钟把目录结构读一遍而不是急着打开 IDE 编译。原因很简单ZeosDBO 虽然用起来是一组组件但内部是严格分层的编译失败时绝大多数错误都能从目录归属判断出问题出在哪一层。这一步读懂了后面装包和排错都能省很多时间。2.1 先看目录哪些是编译入口哪些是排错重点一个正常的 6.0.12 源码包解开后核心目录大致如下zeosdbo-6.0.12/ ├── packages/ │ ├── delphi/ │ └── lazarus/ ├── src/ │ ├── component/ │ ├── dbc/ │ ├── plain/ │ ├── protocol/ │ ├── parsesql/ │ └── compatibility/ ├── test/ └── doc/packages/delphi和packages/lazarus是编译入口前者给 Delphi 用后者给 Lazarus 用。你不需要手动把 src 里所有文件夹加进 IDE 搜索路径包安装成功后这些路径会自动配好。src/component是组件层TZConnection、TZQuery、TZTable、TZStoredProc、TZSQLMonitor 这些能拖到窗体上的组件都在这。src/dbc是数据库连接抽象层里面定义的是一组接口比如 IZConnection、IZStatement、IZResultSet。src/plain负责封装各家数据库客户端动态库的 APIsrc/protocol则是具体协议实现包括各数据库的 SQL 翻译、数据类型转换和事务控制。src/parsesql做 SQL 解析src/compatibility放的是跨版本兼容单元比如 ZClasses 就是放在这个目录附近。这段信息对排错非常关键。比如你连接 MySQL 时报 “Cant load library: libmysql.dll”那不是组件层的问题而是 plain 层在加载客户端库时失败如果 SQL 语句发送后报语法错误那多半要去 protocol 层看它有没有对 SQL 做方言改写。2.2 四层协作一次连接请求在源码里怎么走为了更直观地理解我用一个最简单的连接请求来拆解四层关系。你在窗体上放一个 TZConnection设置 Driver 为 mysql然后调用 Connect。此时 Component 层把连接参数交给 DBC 层DBC 层从驱动管理器里找到对应的 protocol 驱动再由 Plain 层加载 libmysql.dll 或 libmariadb.dll 并调用它的连接函数。连接建立之后查询语句会从 Component 层经过 DBC 层的接口进入 protocol 层的 SQL 解析和协议打包最后通过 plain 层塞给数据库。这个链路决定了两个事情。第一组件层只和接口打交道不看具体数据库实现所以同一个 TZQuery 可以从 MySQL 切到 PostgreSQL只需要换一个 Driver 名。第二如果你要修一条查询速度慢或者数据转换错误的问题真正常改动的地方是 protocol 层不是 Component 层。很多新手在组件事件里反复试最后发现根因在数据类型的映射代码里就是这个原因。在 6.0.12 源码里协议层的类型转换逻辑是完整可读的。比如 Firebird 的 NUMERIC 字段读出来以后怎么转成 TField 的数值类型都有明确分支。你要做的是把断点打在那些转换函数上而不是在界面上瞎试。下面这张表可以帮助你建立“出问题该去哪个目录”的直觉故障类别涉及目录说明找不到客户端库src/plain动态加载 libmysql、libpq 等逻辑在这里SQL 方言不兼容src/protocol协议层负责 SQL 改写与参数展开字段类型错乱src/protocol数据库类型到 TField 类型的映射组件属性不生效src/component组件层属性和事件处理打开包失败packages包工程文件缺失或路径残留这张表不是绝对准确但能帮你先把排查方向定下来不会一上来就把所有代码都翻一遍。2.3 驱动与客户端库依赖常用驱动对照在编译前可以先对照一下驱动清单。下面列出我在 6.0.12 环境下最常碰到的几个驱动及对应客户端库驱动名需要的外部库备注sqlite无需外部 DLL源码内置 SQLite最适合冒烟测试mysqllibmysql.dll 或 libmariadb.dll位数必须和 IDE 一致postgresqllibpq.dll / libpq.soWindows 下建议放到 exe 同目录firebirdfbclient.dll嵌入式模式可用 fbembed.dlloracleoci.dll需要 Oracle Instant Client这里我只列最常用的几个。mssql、sybase、db2 等驱动在 protocol 目录也有对应实现但依赖项不一样用之前最好打开对应协议单元看它在类定义里声明了哪个动态库别想当然。sqlite 驱动之所以最省事是因为它把 SQLite 的 C 源码直接编进了 ZPlainSQLite 单元运行时不依赖外部文件。这也是我建议用 SQLite 做安装冒烟测试的原因环境干净排错范围小不涉及 PATH 和位数问题。2.4 从 test 与 doc 目录反向理解组件行为源码包里的 test 目录很容易被忽略但它其实是理解组件行为的最好入口。test 下按协议分类放着大量测试用例比如你可以在里面找到针对 PostgreSQL 的字段类型测试、针对 SQLite 的自动增量测试、针对字符集的编码测试。这些用例直接调用 DBC 层接口没有界面干扰非常适合用来验证“某个驱动在 6.0.12 里到底支不支持某种特性”。doc 目录里通常有编译说明和组件使用说明比如各版本支持的数据库列表、新版本的行为变化。有一件事我吃过亏ZeosDBO 对某些数据库的默认选项是会随版本变化的比如 SQLite 的 foreign_keys 默认开没开不同版本不一样。这种信息在源码的单元注释里有时比在文档里更明确。看源码时先搜default和FDefault前缀往往能发现很多藏在属性里的“隐藏开关”。明白目录结构之后再进入编译安装就不会觉得那是一堆乱文件了。编译顺序和路径配置也可以直接根据目录结构推导出来。3. 编译并安装源码包Lazarus 与 Delphi 两条路径ZeosDBO 6.0.12 的源码包不提供预编译的安装程序你必须自己把包工程编译并安装进 IDE。这个过程在 Lazarus 和 Delphi 里略有不同但核心思路一致找到对应包文件按依赖顺序编译安装设计期包最后用 SQLite 做一次真实连接验证。3.1 准备环境路径、位数和客户端库检查我先说环境。解压源码包的路径不要带空格和中文这是 Delphi 时代就有的老毛病。宁可放在C:\dev\zeosdbo-6.0.12也不要放在C:\Users\张三\Downloads\我的资料这类路径下。虽然新版 Lazarus 对路径容忍度高但某些 make 脚本仍会在空格处断开。然后检查 IDE 位数。ZeosDBO 编译时会根据 IDE 的位数决定加载哪种客户端库接口。如果 IDE 是 32 位数据库客户端库也必须是 32 位混用 64 位 libpq.dll 和 32 位 Lazarus 会在连接时直接报加载失败。这个坑我在 PostgreSQL 上踩过好几次。解压这一步可以直接用命令行处理unzip zeosdbo-6.0.12.zip -d C:/dev/ cd C:/dev/zeosdbo-6.0.12解压完成后建议先看一眼packages/lazarus和packages/delphi里是否都有 lpk 和 dpk 文件。如果只有其中一个说明你拿到的源码包是针对某个 IDE 裁剪过的安装流程就得跟着实际文件走。3.2 Lazarus 安装用 lpk 包编译并注册到 IDELazarus 下安装 ZeosDBO 最标准的做法是从 IDE 的 Package 菜单打开包文件但在命令行里先编译一次能更快暴露环境问题。进入包目录后执行cd C:/dev/zeosdbo-6.0.12/packages/lazarus lazbuild zeosdbo.lpklazbuild是 Lazarus 自带的命令行编译工具。如果这一步能顺利编译完成说明源码本身和你的 FPC 版本兼容。如果报错先看错误信息里提到哪个单元然后回到第 2 章的目录结构对应关系去判断。比如找不到ZClasses多半是兼容性单元路径没有正确加入包文件可以打开 lpk 手动检查SearchPaths段。命令行编译成功后还需要把包安装进 IDE 才能在设计期看到组件。此时打开 Lazarus菜单选「Package」→「Open Package File (.lpk)」找到C:/dev/zeosdbo-6.0.12/packages/lazarus/zeosdbo.lpk。加载后左侧组件树会列出包内所有单元点右上角的「Compile」按钮编译通过后再点「Install」按钮。点击 Install 后Lazarus 会提示需要重建 IDE。确认后等待重启组件面板上会出现一个新的Zeos Access页里面就是 TZConnection、TZQuery、TZTable 等组件。如果重启后找不到去「Components」→「Configure Installed Packages」里确认 zeosdbo 已经在安装列表并且没有被勾掉。3.3 Delphi 安装按依赖顺序编译包Delphi 下的安装路径稍微讲究一些。老版本的 ZeosDBO 包里可能是一个聚合包直接打开ZeosDbo.dpk就能编译安装但 6.0.12 的包结构也可能被拆成了多个 dpk这时候必须按依赖顺序编译否则 Delphi 会报“上一个包还没编译”的错误。我一般会进到 packages/delphi 目录先看包文件列表cd C:/dev/zeosdbo-6.0.12/packages/delphi dir *.dpk如果只有一个 ZeosDbo.dpk那就简单在 Delphi 中打开 dpk 后右键选择「Compile」编译通过再右键「Install」。注意 Install 会把设计期包注册到 IDE 中组件面板会出现 Zeos Access 页。如果看到多个 dpk文件名通常类似ZCore.dpk、ZParseSql.dpk、ZPlain.dpk、ZDbc.dpk、ZComponent.dpk。这时候按依赖顺序编译ZCore 是最基础的运行时库ZParseSql 依赖 ZCoreZPlain 依赖 ZCoreZDbc 依赖 ZPlain 和 ZParseSqlZComponent 最后编因为组件层依赖前面所有层。每编完一个包保持它在 IDE 中处于打开状态再编下一个。装到最后再把 ZComponent 安装为设计期包。这里有一个容易被忽略的点Delphi 打开 dpk 时如果工程里引用的源文件路径还是绝对路径而你的源码包不在预期目录会弹很多“找不到源文件”的错。此时打开「Tools → Options → Environment Variables」检查 Delphi 的 Library 路径把packages和src下的相关目录加进库搜索路径最省事。3.4 冒烟测试用 SQLite 验证安装成功安装完成后不建议直接去连公司数据库先用 SQLite 做一次冒烟测试。SQLite 不需要外部 DLL环境最干净。新建一个控制台项目或简单 Application放一个 TZConnection写下面这段代码var conn: TZConnection; begin conn : TZConnection.Create(nil); try conn.Driver : sqlite; conn.Database : C:/temp/smoke.db; conn.Connect; WriteLn(connected: , conn.Connected); conn.Disconnect; finally conn.Free; end; end;这段代码把驱动固定为 sqlite指定数据库文件路径然后调用 Connect。如果前面包安装有问题这里会在 Connect 处直接抛异常错误信息会指向具体单元如果一切正常控制台会输出connected: TRUE。我用 SQLite 做冒烟测试是因为它绕开了所有外部客户端库的干扰。你可以先在内存模式测一下连接参数再用物理文件测一遍读写。物理文件测试的下一步就是第 4 章里要说的完整查询流程。4. 上手配置与读数据连接参数、参数化 SQL 和事务控制组件安装和冒烟测试通过之后就可以开始正式接业务了。这一章我把使用 ZeosDBO 最常见的四个场景拆开讲连接参数怎么配、查询怎么写、事务怎么控、以及出问题时怎么抓真实 SQL。每段代码都可以直接抄到工程里改改参数用。4.1 连接参数哪些属性是必修课TZConnection 是最容易让人困惑的组件因为它的属性既有像传统 ADO 一样的连接信息又有 Zeos 独特的 Properties 扩展。我用一张表把常用属性列出来属性示例值作用Driversqlite / mysql / postgresql选择协议驱动HostName127.0.0.1数据库主机地址Port5432端口不填则用驱动默认值DatabaseC:/data/test.db 或 testdb数据库文件或库名Userroot用户名Password123456密码PropertiescodepageUTF8字符集、行为开关等扩展参数Properties 是最有 Zeos 风格的地方它是一组以分号或换行分隔的键值对直接控制驱动行为。我平时最常用的是codepage比如连接 PostgreSQL 时如果数据库是 UTF-8我会写成conn.Properties.Add(codepageUTF8);这里codepage告诉 Zeos 用 UTF-8 解释客户端和服务端之间的字符串。加在 Properties 里的参数会在协议层生效不同驱动的可用键不完全一样。最稳的查法是打开对应 protocol 单元的源码搜Properties或AddProperty看驱动注册了哪些参数。不推荐盲目照搬网上的配置。另外LibraryLocation属性也很重要。当你不想把客户端库放进系统 PATH 时可以显式指定动态库路径conn.Driver : mysql; conn.LibraryLocation : C:/libs/libmariadb.dll;这个属性在连接前设置Zeos 会优先从这个路径加载客户端库而不是去 PATH 里找。多版本客户端库冲突时这就是后悔药。4.2 查询和参数化 SQL直接用代码说话连接建立后最常打交道的组件是 TZQuery。一个带参数查询的完整示例var conn: TZConnection; qry: TZQuery; begin conn : TZConnection.Create(nil); qry : TZQuery.Create(nil); try conn.Driver : sqlite; conn.Database : demo.db; conn.Connect; qry.Connection : conn; qry.SQL.Text : SELECT id, name FROM users WHERE age :age; qry.ParamByName(age).AsInteger : 18; qry.Open; while not qry.EOF do begin WriteLn(qry.FieldByName(id).AsString, , qry.FieldByName(name).AsString); qry.Next; end; finally qry.Free; conn.Free; end; end;这段代码里SQL.Text指定的是带命名参数:age的 SQLParamByName(age).AsInteger : 18给参数赋值然后Open执行查询并返回结果集。循环部分用EOF判断是否结束Next移到下一行。这里要特别说明查询语句用Open增删改语句用ExecSQL。很多新人把Open用在 INSERT、UPDATE、DELETE 上结果提示“没有结果集”或直接报错。执行写操作时应该把 SQL 换成对应语句再调用ExecSQL。参数化查询不只是为了防注入更是为了让 Zeos 正确推导参数类型。例如:age如果直接拼在 SQL 里MySQL 可能把它当成字符串造成索引失效用参数化可以让驱动按整数类型发送减少隐式转换。4.3 事务边界AutoCommit 与显式事务ZeosDBO 默认的 AutoCommit 是 True也就是每条 SQL 都自动提交。但在真实业务里一次操作往往要同时更新多张表必须手动控制事务。常见做法是把 AutoCommit 设为 False然后显式调用 StartTransaction、Commit、Rollbackconn.AutoCommit : False; conn.StartTransaction; try qry.SQL.Text : UPDATE accounts SET balance balance - ? WHERE id ?; qry.Params[0].AsFloat : 100; qry.Params[1].AsInteger : 1; qry.ExecSQL; qry.SQL.Text : UPDATE accounts SET balance balance ? WHERE id ?; qry.Params[0].AsFloat : 100; qry.Params[1].AsInteger : 2; qry.ExecSQL; conn.Commit; except conn.Rollback; raise; end;这段代码把一笔转账的两个更新放在同一事务里任何一个失败都会执行 Rollback保证账户余额一致。Params[0]是按位置访问参数比ParamByName更高效代价是要小心 SQL 里参数的顺序别写错。关于事务我的经验是不要把事务绑定在组件的事件里而是在业务函数里显式控制边界。Zeos 的 DBC 接口本身支持事务嵌套但嵌套事务容易造成提交语义混乱除非驱动明确支持否则我一般只用一层显式事务。4.4 抓 SQL让 TZSQLMonitor 帮你还原现场业务代码跑起来后如果发现查询结果不对或怀疑 SQL 拼接有问题不要靠猜用 TZSQLMonitor。这个组件可以挂在 TZConnection 上记录 Zeos 实际发送给数据库的 SQLZSQLMonitor1.Connection : conn; ZSQLMonitor1.FileName : trace.log; ZSQLMonitor1.Active : True; conn.Connect; // 执行你的业务查询FileName指定日志输出文件Active打开监控。连接后每一条 SQL 都会被写入 trace.log包括参数替换后的完整语句。这个方法比在数据库端开慢查询日志更直接因为你能看到 Zeos 发出去的到底是什么。如果不想写文件也可以接管它的 OnTrace 事件把日志输出到自己的日志系统。这里有个小提醒TZSQLMonitor 本身有性能损耗生产环境别开着跑只在排查问题时临时启用。尤其是循环大批量插入时SQL 日志会让速度慢好几倍。5. ZeosDBO 避坑实录编译与运行阶段的高频问题ZeosDBO 用久了你会发现很多问题其实不是组件本身的问题而是环境、位数、字符集和多线程并发造成的。这一章我按“现象 → 原因 → 解决”的方式记录四类我踩过或帮别人排查过的高频问题。5.1 连接 MySQL 报 “Cant load library: libmysql.dll”现象程序在窗体上拖了 TZConnectionDriver 设为 mysql数据库地址、用户名密码都填对了一执行 Connect 就抛异常提示找不到 libmysql.dll。用自带数据库工具能正常连接排除服务器问题。原因Zeos 的 mysql 协议并不内置完整 MySQL 客户端它在连接时通过 plain 层动态加载 libmysql.dll 或 libmariadb.dll。这个 dll 要在 PATH、exe 目录或 LibraryLocation 能找到。另一个常见原因是 IDE 是 32 位而你从 MySQL 官网下载的是 64 位库。解决优先把客户端库放到 exe 同目录位数和 IDE 一致。如果还不行就在代码里显式指定库路径conn.Driver : mysql; conn.LibraryLocation : C:/dev/connectors/libmariadb.dll;我一般用 MariaDB 的客户端库替代 MySQL 官方库因为 MariaDB Connector 对旧版 MySQL 协议兼容性更好而且自带一些安全修复。如果你用LibraryLocation也找不到就检查一下路径是否包含空格有些版本的 Zeos 对带空格的路径处理有 bug先临时放到无空格路径测试。5.2 SQLite 读出中文乱码现象SQLite 里存的数据用数据库工具看是正常中文但通过 TZQuery 查出来变成乱码甚至显示成问号。表结构是 varchar 或 text没有用 NVARCHAR。原因SQLite 存储的字符串默认是 UTF-8但 Zeos 连接时如果没有告诉它使用 UTF-8 编码它会按默认代码页解释字节流中文就被拆错。这个问题常见于从旧工程迁移过来的情况之前用的驱动把字符串直接当 Ansi 处理。解决在连接前加上 page 属性conn.Driver : sqlite; conn.Properties.Add(codepageUTF8); conn.Connect;如果加了 codepage 依旧乱码再试Properties.Add(controls_cn1)。controls_cn会影响 Zeos 对字符串字段里控制字符的处理方式某些版本里它也会影响 UTF-8 解析。乱码问题千万不要去改 TField 的编码属性那是治标不治本正确位置永远是连接层。5.3 多线程共用同一个 TZConnection 导致崩溃现象程序开了多个线程每个线程都使用一个全局的 TZConnection 执行查询。运行一段时间后某个线程报 “Connection is busy” 或直接访问冲突崩溃偶发且难以复现。原因TZConnection 和它内部的连接对象不是线程安全的。同一个连接在同一时刻只能被一个线程使用你无法指望依赖简单的临界区保护来串行化因为 Zeos 的 DBC 接口在状态切换时会把连接标记为 busy第二个线程再调用时直接失败。解决每个线程创建自己独立的 TZConnection 和 TZQuery用完释放。线程结束后不要把连接丢到全局池里复用除非你自己实现了严格的借出和归还逻辑。下面是一个最小线程结构var conn: TZConnection; begin conn : TZConnection.Create(nil); try conn.Driver : postgresql; conn.HostName : 127.0.0.1; conn.Database : mydb; conn.User : postgres; conn.Password : secret; conn.Connect; // 线程内只使用这个 conn 执行 SQL finally conn.Free; end; end;每个线程独立连接虽然开销略大但换来了稳定。真正的连接池需求可以考虑用 Zeos 自带的连接池但不要在业务里拿单个连接做并发那是拿稳定性换性能。5.4 旧工程换源后编译报 “Cant find unit ZClasses”现象把一个以前用 ZeosDBO 6.0.x 写的工程从旧机器迁移到新环境重新安装 6.0.12 源码后编译工程报错找不到单元 ZClasses。旧机器上同一套代码是能编译的。原因ZClasses 是 Zeos 的基础单元通常放在 compatibility 或 core 相关目录里。报这个错说明 IDE 的搜索路径里没有包含该单元所在目录或者旧版本的包还在 IDE 环境中残留导致编译器优先找到了旧包路径里的 ZClasses而旧包路径已经失效。解决先在 IDE 的搜索路径里加上src/compatibility目录同时检查是否有多个 zeos 包版本被同时安装。Lazarus 下打开「Components」→「Configure Installed Packages」把旧版本包反装只保留 6.0.12 的包。Delphi 下则去「Tools → Options → Delphi Options → Library-Win32」里检查 Library path删除指向旧 zeos 源码的路径。如果还是不行用下面的命令行方式重建包cd C:/dev/zeosdbo-6.0.12/packages/lazarus lazbuild --clean-all zeosdbo.lpk lazbuild zeosdbo.lpkclean-all会清掉该包的历史编译缓存。注意这个命令只对 Lazarus 包有效Delphi 下请在包管理器里手动执行 Build 然后删除 DCU 缓存目录。大多数情况下清理残留包比补路径更重要。6. 进阶验证版本、抓真实 SQL 和扩展你自己的驱动装好 6.0.12 之后我建议你做三件事能让你后面用得更踏实验证装入 IDE 的组件确实是 6.0.12把协议层的真实调用确认一遍以及搞清楚怎么扩展一个自定义驱动。先验证版本。虽然包安装成功但 IDE 里可能残留旧版本包。最直接的办法是在源码目录里搜索版本字符串grep -R 6.0.12\|ZEOS_VERSION src packages | head -20如果只有少数字段命中了 6.0.12说明源码本身没有混版本。然后写一个最小的连接测试通过 protocol 对象输出协议名称conn.Connect; WriteLn(conn.Protocol.Name); conn.Disconnect;conn.Protocol只有在连接后有效返回的是当前激活的协议接口Name会返回协议名。这一步能确认你连接的不是缓存里的旧驱动。然后是抓真实 SQL。TZSQLMonitor 适合看单条 SQL但它只记录发送给驱动层之前的语句。如果你想确认协议层有没有改写 SQL就在 IDE 的 Debug 模式下在ZProtocol.pas的Prepare和Execute方法里下断点。这里你会看到 Zeos 是怎么把 TZQuery 的 SQL 拆成数据库认识的原生语句的很多诡异的“数据库不识别语法”其实是协议层改写的边界问题。最后说扩展驱动。Zeos 的驱动框架其实是一个可插拔设计新增一个数据库协议并不需要改组件层。你需要做的是在 protocol 目录下新写一个协议单元继承现有的 ZAbstractConnection 或对应驱动类实现连接、事务和结果集接口然后在 ZDriverManager 里注册这个新协议。注册代码的核心逻辑大致是uses ZDriverManager, ZMyProtocol; initialization ZDriverManager.RegisterDriver(TZMyProtocolDriver.Create); end.这段代码写在单元 initialization 段IDE 启动加载包时就会执行注册。之后 TZConnection 的 Driver 下拉框里就会出现新的驱动名。这三件事做完你对这份 6.0.12 源码就不再是“用过”而是“改过”。从那以后我每次拿到新的 Zeos 源码包都强制自己走一遍先编译安装再用 SQLite 跑最小连接最后打开 TZSQLMonitor 抓一条真实 SQL。这三步看着笨但能挡住大量换版本引起的玄学问题。希望这篇笔记能帮到你少走我之前走过的弯路。本文还有配套的精品资源点击获取