简介面向 Delphi6 与 C/S 数据库开发者InterBase 6.0 安装包与开发组件合集提供了从数据库引擎部署到示例库验证的完整材料适合需要理解关系型数据库运行机制、进行旧项目维护或客户端/服务器应用实践的中级开发者。压缩包共 130 个文件约 4.86MB以 C 源码、示例文件、可执行程序、DLL、头文件和库文件为主并配有说明文档、SQL 脚本、配置文件和示例数据库覆盖安装、运行、开发调用与卸载清理等环节。已有 341 人学习说明其在数据库与 InterBase 技术栈中仍具参考需求。读者可据此了解核心动态库的调用关系、安装配置流程、事务处理与权限管理机制也能从源码和脚本中梳理 API 连接、触发器、存储过程及备份维护思路并借助随包示例库快速搭建测试环境、排查连接与部署问题。1. InterBase 6.0 这套资源到底值不值得拆先看它把“控件 源码 数据库”绑在哪如果你拿到的是一个 InterBase 6.0 的数据库应用源码包先别急着找主窗体。真正决定它能不能跑起来的往往是控件层怎么连库、事务边界放在哪以及源码里的初始化脚本是否和当前实例匹配。这份资源围绕 InterBase 6.0 整理了控件示例、数据库应用源码和配套脚本适合还在维护历史库、需要把老系统接回可复现开发流程的人。它不负责把你教会 SQL但能把“库能起、控件能连、源码能编、数据能恢复”这条链路摊开。下面按我拆包时的顺序走先跑实例再谈控件和源码。2. 把实例跑起来从服务端安装到第一个 dialect 3 数据库2.1 先确认实例和 isql 能进不要先编译源码老数据库资源最容易翻车的地方不是 SQL 写错而是实例根本没起来。InterBase 6.0 默认走 3050 端口服务端进程起来之后isql是最小验证工具它不依赖控件、不依赖应用层能连上就说明服务端、端口、库路径这三件事至少通了两件。我一般先在本机确认端口在听再用isql连一个空库或已有库确认客户端和服务端没有位数错配。# 确认 3050 端口在监听不同平台把 grep 换成 findstr netstat -an | grep 3050 # 用 isql 直接连目标库绕过应用层和控件层 isql -user SYSDBA -password masterkey localhost:/opt/db/demo.ib这段命令的逻辑很简单netstat看端口isql看库。-user和-password是 InterBase 的默认管理账号参数实际环境如果改过密码就换成自己的localhost:表示走本机回环远程实例换成服务端地址。路径必须写服务端能看到的绝对路径不能把客户端盘符路径直接抄进去。isql连不上时先别怀疑源码先看服务进程、路径权限和客户端库版本。常见做法是先用isql进交互环境再执行CONNECTCONNECT localhost:/opt/db/demo.ib USER SYSDBA PASSWORD masterkey;CONNECT的参数里库路径、用户名、密码三者要匹配。如果这里报unavailable database应用层大概率也是同一个错后面第 5 章会拆这个报错。先把这个最小链路跑通再谈控件连接能省掉一半排查时间。2.2 用 dialect 3 建库和表先把页大小和字符集定下来InterBase 6.0 的 SQL 方言有 dialect 1 和 dialect 3 的差异老源码里经常混着写。我的建议是新库统一用 dialect 3日期时间类型、NUMERIC(18,2)和后续的生成器写法都更顺如果源码明确依赖 dialect 1 的旧行为再单独建库不要在一个库里来回切。建库时页大小和默认字符集要一次定好后面改代价很大。SET SQL DIALECT 3; CREATE DATABASE localhost:/opt/db/demo.ib USER SYSDBA PASSWORD masterkey PAGE_SIZE 4096 DEFAULT CHARACTER SET NONE; CREATE TABLE CUSTOMER ( ID INTEGER NOT NULL, NAME VARCHAR(64) CHARACTER SET NONE, AMOUNT NUMERIC(18,2), CREATED_AT TIMESTAMP, CONSTRAINT PK_CUSTOMER PRIMARY KEY (ID) );SET SQL DIALECT 3告诉isql后续按 dialect 3 解析CREATE DATABASE里的PAGE_SIZE 4096是页大小老库常见 4096小库用 1024/2048 也能跑但不要拍脑袋选太大DEFAULT CHARACTER SET NONE表示库级不强制字符集转换这在老系统里很常见代价是中文要靠应用层自己保证编码一致。VARCHAR(64) CHARACTER SET NONE是字段级字符集和库级保持一致减少隐式转换。NUMERIC(18,2)存金额TIMESTAMP存创建时间都是 dialect 3 下比较稳的写法。执行脚本用isql的-i参数isql -user SYSDBA -password masterkey -i init.sql -q-i指定输入脚本-q安静模式适合批处理调试阶段可以去掉-q加上-e看回显。注意CREATE DATABASE要在未连接库的会话里执行不要先CONNECT再建库。建完先用isql查一下系统表确认表真的落地了。2.3 生成器、触发器和初始化脚本要一起验数据库应用源码里主键生成通常靠 generator trigger。InterBase 6.0 的GEN_ID是原子递增触发器在BEFORE INSERT里赋值能避免应用层并发取号。这里有个细节如果字段是NOT NULL触发器里要判断NEW.ID IS NULL OR NEW.ID 0否则手工插入 0 会撞主键。初始化脚本里把 generator 置 0插入测试数据时让触发器自己取号。SET SQL DIALECT 3; CONNECT localhost:/opt/db/demo.ib USER SYSDBA PASSWORD masterkey; CREATE GENERATOR GEN_CUSTOMER_ID; SET GENERATOR GEN_CUSTOMER_ID TO 0; SET TERM ^ ; CREATE TRIGGER BI_CUSTOMER_ID FOR CUSTOMER ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.ID IS NULL OR NEW.ID 0) THEN NEW.ID GEN_ID(GEN_CUSTOMER_ID, 1); END^ SET TERM ; ^ INSERT INTO CUSTOMER (NAME, AMOUNT, CREATED_AT) VALUES (Customer-A, 100.50, CURRENT_TIMESTAMP); COMMIT; SELECT ID, NAME, AMOUNT FROM CUSTOMER;SET TERM ^是isql的语句结束符切换触发器体里有分号不切结束符会提前截断GEN_ID(GEN_CUSTOMER_ID, 1)每次取 1 步长BEFORE INSERT保证在约束检查前赋值。插入测试用英文名是为了先排除字符集干扰等控件层跑通再换中文数据。COMMIT不能漏isql默认事务不自动提交查不到数据先看是不是没提交。3. 控件层怎么接TIBDatabase、TIBTransaction 与连接参数的边界3.1 控件选型IBX、dbExpress、ODBC 各管一段这套资源里的“控件”不是泛指界面按钮而是数据库连接控件。老 InterBase 数据库应用常见三条路IBX 原生控件、dbExpress 轻量驱动、ODBC/JDBC 桥接。IBX 的优点是事务控制细、和数据集组件贴合紧适合源码里已经有TIBDatabase、TIBTransaction、TIBQuery的项目dbExpress 更轻但 InterBase 6.0 时代的驱动版本老事务参数不如 IBX 直观ODBC/JDBC 适合非 Delphi 客户端、报表工具或跨语言服务但多一层驱动字符集和锁行为要多验一遍。接法适合场景主要边界IBX 控件老源码已有数据模块需要显式事务控件包版本要和 IDE 匹配不能混装两套dbExpress轻量查询、跨库迁移驱动版本老事务边界要自己封ODBC/JDBC报表、外部工具、非 Delphi 服务多一层驱动字符集和锁等待要实测我的选型顺序是源码里已经用 IBX就继续用 IBX别为了“新”去换驱动源码里是 dbExpress就先把 dbExpress 的连接参数跑通不要混入 IBX 控件只有外部工具接库时才考虑 ODBC。混用最典型的翻车是数据模块里一套事务外部工具另一套连接锁冲突时根本不知道谁持有事务。3.2 TIBDatabase 与 TIBTransaction 的参数怎么落IBX 的连接参数集中在TIBDatabase.Params里事务参数集中在TIBTransaction.Params里。连接参数至少要有user_name、password、lc_ctypeDatabaseName写服务端可见路径。lc_ctypeNONE和库级字符集保持一致别一边库是NONE一边客户端强行UTF8老库容易出乱码。LoginPromptFalse是为了让服务启动时不弹登录框适合后台服务和自动化测试。参数示例值说明DatabaseNamelocalhost:/opt/db/demo.ib服务端可见路径远程换地址user_nameSYSDBA管理账号生产应换独立账号passwordmasterkey默认密码部署后必须改lc_ctypeNONE与库级字符集一致减少隐式转换LoginPromptFalse后台服务不弹框SQLDialect3与建库方言一致事务参数我一般用read_committedrec_versionnowait做调试组合read_committed读已提交rec_version读记录的最新版本nowait遇到锁冲突立刻报错方便把锁问题暴露出来。生产环境把nowait换成wait再加超时避免用户点一下等半天。下面这段是数据模块里最常见的初始化写法var DB: TIBDatabase; TR: TIBTransaction; Q: TIBQuery; begin DB : TIBDatabase.Create(nil); DB.DatabaseName : localhost:/opt/db/demo.ib; DB.Params.Add(user_nameSYSDBA); DB.Params.Add(passwordmasterkey); DB.Params.Add(lc_ctypeNONE); DB.LoginPrompt : False; DB.SQLDialect : 3; TR : TIBTransaction.Create(nil); TR.DefaultDatabase : DB; TR.Params.Add(read_committed); TR.Params.Add(rec_version); TR.Params.Add(nowait); DB.DefaultTransaction : TR; Q : TIBQuery.Create(nil); Q.Database : DB; Q.Transaction : TR; Q.SQL.Text : SELECT ID, NAME FROM CUSTOMER WHERE NAME LIKE :NAME; Q.ParamByName(NAME).AsString : %A%; TR.StartTransaction; try Q.Open; while not Q.Eof do begin // 这里只做读取不要在循环里等用户输入 Q.Next; end; TR.Commit; except TR.Rollback; raise; end; end;代码里的关键点是DB.DefaultTransaction : TR不设的话某些数据集会自己找默认事务事务边界就散了Q.Transaction : TR显式绑定查询和提交必须在同一个事务对象上。TR.Params的顺序不影响语义但nowait只适合调试生产换wait。异常里必须Rollback否则连接会挂着事务后面再查就锁。3.3 从 TIBQuery 到 ClientDataSet数据集链的职责要分清老数据库应用源码里常见一条链TIBQuery取数据TDataSetProvider打包TClientDataSet给界面做离线编辑。这条链的好处是 UI 不直接持有数据库游标用户改完再ApplyUpdates事务边界可以收在数据模块方法里。坏处是很多人把TClientDataSet当数据库用忘了ApplyUpdates也要事务最后更新失败却找不到错在哪。procedure TDM.OpenCustomers(const AName: string); begin if not DB.Connected then DB.Open; if not TR.InTransaction then TR.StartTransaction; try QCustomer.Close; QCustomer.SQL.Text : SELECT ID, NAME, AMOUNT, CREATED_AT FROM CUSTOMER WHERE NAME LIKE :NAME ORDER BY ID; QCustomer.ParamByName(NAME).AsString : % AName %; QCustomer.Open; CDSCustomer.Close; CDSCustomer.Open; // 通过 Provider 取包 except TR.Rollback; raise; end; end;QCustomer的LIKE :NAME用参数绑定不要拼字符串避免注入和引号问题ORDER BY ID让分页和调试有稳定顺序。CDSCustomer.Open触发TDataSetProvider取数据PacketRecords默认 -1 取全量大结果集设成 100 或 200 分批取。AName为空时%%会全表扫数据量大要加限制条件。读取事务提交后CDS 里的数据还在但更新必须另开事务procedure TDM.SaveCustomers; begin if not TR.InTransaction then TR.StartTransaction; try CDSCustomer.ApplyUpdates(0); TR.Commit; except TR.Rollback; raise; end; end;ApplyUpdates(0)里的 0 表示任何更新错误都抛异常不要静默吞掉TR.Commit之后 CDS 的更新日志才清空。事务方法放在数据模块里不要放在按钮OnClick里界面只负责收集输入。这样后面换界面、加服务层事务边界不用重写。4. 源码包怎么读数据模块、事务边界和三层数据集的分工4.1 先看依赖和目录类型不要先点编译拿到数据库应用源码包第一件事不是打开主窗体而是看目录类型和依赖。常见结构会按src、db、scripts、packages、docs分开src放主程序和数据模块db放建库脚本和初始化数据scripts放备份恢复脚本packages放控件包docs放参数说明。先读readme、*.ini、*.sql把连接参数和库版本对一遍再决定要不要装控件包。目录类型作用先看什么src主程序、数据模块、窗体.dpr的uses和Requiresdb建库、建表、初始化数据方言、字符集、generator 初始值scripts备份、恢复、校验gbak/gfix参数和目标路径packages控件包包依赖顺序、版本号docs参数和部署说明默认账号、端口、路径约定依赖识别最直接的办法是打开项目组看Requires列表缺哪个包先装哪个。不要一上来改源码先把“缺包”和“代码错”分开。包版本不对时IDE 会给一堆“找不到属性”的错看起来像源码坏了其实只是控件版本不匹配。我的习惯是先备份.dpr和.dfm再动包引用改坏了能退。4.2 数据模块里的事务边界决定后面好不好维护数据模块是老数据库应用的枢纽连接、事务、查询、Provider、ClientDataSet 都挂在这里。事务边界如果散在窗体事件里后面加一个批量导入就会到处补StartTransaction。我更愿意把事务收在数据模块方法里窗体只调用OpenCustomers、SaveCustomers这种语义方法不直接碰TR。type TDM class(TDataModule) DB: TIBDatabase; TR: TIBTransaction; QCustomer: TIBQuery; DSPCustomer: TDataSetProvider; CDSCustomer: TClientDataSet; end;这段声明不是让你照抄类名而是看职责DB管连接TR管事务QCustomer管服务端查询DSPCustomer管打包CDSCustomer管界面离线数据。DSPCustomer.DataSet指向QCustomerCDSCustomer.ProviderName指向DSPCustomer这三个对象的顺序不能乱。源码里如果出现两个TIBTransaction先确认是不是读写分离还是历史遗留两个事务同时写同一张表锁冲突会很难查。事务边界还有一个容易忽略的点DDL 也要提交。建表、建索引、SET GENERATOR之后不COMMIT别的会话看不到应用启动时就会报“表不存在”。初始化脚本里每个 DDL 段落后面跟一个COMMIT比最后统一提交稳。4.3 编译顺序和运行时资源别把路径问题当成代码问题编译顺序一般是先装/注册控件包再编译数据模块和公共单元最后编译主程序。IDE 里直接Build All也行但包没装好时Build All会把包错误和代码错误混在一起。运行时资源包括窗体 DFM、图标、ini、SQL 脚本这些不在搜索路径里时编译能过运行才报错。老源码常见做法是把连接参数放 ini 或注册表先找到那个配置文件再改库路径。顺序动作检查点1安装控件包包依赖是否齐全版本是否匹配2编译数据模块TIBDatabase等控件是否识别3编译主程序窗体 DFM 是否同步4放运行时资源ini、SQL、图标是否在搜索路径位数问题要单独提InterBase 6.0 时代的客户端库很多是 32 位现代 IDE 如果切到 64 位可能找不到匹配的客户端库。源码是 32 位工程就先按 32 位编不要为了“统一”硬切 64 位。切之前先确认客户端库、控件包、服务端三边位数一致否则连接阶段就会报库加载失败。5. 避坑与排查连接、字符集、事务、控件版本的五个高频翻车点5.1 连接报 unavailable database先分服务、路径、权限、位数现象是应用和isql都连不上报unavailable database。原因通常四类服务没起、路径不是服务端可见路径、库文件权限不对、客户端和服务端位数不匹配。解决顺序是先isql本机连再查端口再查路径权限最后看客户端库。别在应用层加一堆日志先把这个最小链路跑通。# 端口和服务进程先看 netstat -an | grep 3050 # 用 isql 直接验证库路径不经过控件 isql -user SYSDBA -password masterkey localhost:/opt/db/demo.iblocalhost:后面必须是服务端路径不是客户端映射盘。isql能连、应用不能连问题就在控件参数或客户端库isql也不能连问题在服务端。这个分叉点先定下来后面少走很多弯路。5.2 中文乱码库、字段、客户端三处字符集要一致现象是isql里看正常应用里中文变问号或乱码。原因是库级DEFAULT CHARACTER SET NONE、字段CHARACTER SET NONE、客户端lc_ctype三者不一致或者应用层按 ANSI 写、按 UTF-8 读。InterBase 6.0 对多字节字符集的支持有限老系统常见做法是库内存单字节应用层统一转换。不要用VARCHAR存多字节中文再按字节长度截断截断后半个字符就坏了。检查点常见值处理库级字符集NONE与客户端保持一致字段字符集NONE不要字段和库混用客户端lc_ctypeNONE数据模块里显式设置应用编码ANSI/UTF-8入口出口统一转换先固定一种编码再谈数据迁移。乱码数据不要直接UPDATE修先备份确认原字节再转。5.3 事务锁等待长事务和 nowait 是双刃剑现象是更新卡住或者报lock conflict on no wait transaction、死锁。原因是事务没提交、界面在事务里等用户输入、nowait遇到锁立即报错。血泪经验是不要把StartTransaction放在按钮里然后弹窗等确认用户去泡杯茶锁就一直挂着。正确做法是先把数据读到TClientDataSet用户改完再开事务ApplyUpdates。// 错误做法事务里等用户输入 TR.StartTransaction; QCustomer.Edit; // ... 等用户点确认 ... TR.Commit;排查时另开一个isql会话对同一行执行UPDATE看是否阻塞。阻塞就找持锁会话别急着重启服务。生产环境把nowait换成wait加超时调试环境保留nowait暴露问题。5.4 控件版本不匹配缺包和属性错先分开现象是打开源码缺TIBDatabase或者属性名不认识编译报找不到某个包。原因是源码依赖的控件包版本和当前 IDE 不一致包安装顺序不对或者混装了两套 IBX。解决是先看packages里的包依赖按Requires顺序装不要同时装两套来源不同的 IBX检查Library Path是否指到旧包。改源码前先备份.dpr和.dfm包引用改坏了能退。缺包时 IDE 的报错会指向uses行但真正原因可能在包没注册。先装包再编译别把包错误当代码错误改。5.5 备份恢复后主键冲突generator 要校准现象是gbak恢复后插入报主键重复。原因是 generator 当前值落后于表内最大 ID或者初始化脚本把 generator 重置了或者有人手工插入过 ID。解决是恢复后先查最大 ID再把 generator 设到不小于它的值。SELECT MAX(ID) FROM CUSTOMER; SET GENERATOR GEN_CUSTOMER_ID TO 1000; COMMIT;先查MAX(ID)如果最大值是 1000SET GENERATOR设 1000下一次GEN_ID(...,1)取 1001并发环境设大一点更稳。SET GENERATOR是 DDL别忘了COMMIT。恢复演练不要覆盖原库恢复到新库再校验。6. 验证与调优用 gbak 恢复演练和索引计划把问题提前暴露6.1 备份不做恢复演练等于留一个没有后悔药的坑老库最怕的不是日常查询慢而是备份文件打不开。我拿到任何一套 InterBase 6.0 资源都会先做一次“备份到新库恢复”的演练不覆盖原库恢复完用gfix做全量校验。备份恢复不做演练等真出事时才发现路径、权限、页大小对不上那就没有后悔药了。# 1) 逻辑备份 gbak -b -v -user SYSDBA -password masterkey \ localhost:/opt/db/demo.ib /opt/backup/demo.fbk # 2) 恢复到新库目标库必须不存在 gbak -c -v -user SYSDBA -password masterkey \ /opt/backup/demo.fbk localhost:/opt/db/demo_restore.ib # 3) 全量校验 gfix -v -full localhost:/opt/db/demo_restore.ib-b是备份-c是创建恢复-v输出详细过程恢复目标写新库名避免覆盖原库。gfix -v -full做全量校验输出没有错误再继续。恢复后还要跑一遍第 2 章的建表脚本对比确认 generator、触发器、索引都在。验证项命令通过标准备份文件生成gbak -b -v ...无报错文件大小非 0恢复到新库gbak -c -v ...目标库可连接结构校验gfix -v -full ...无一致性错误数据抽查isql查关键表行数、主键、generator 正常6.2 用计划看索引别让 LIKE 把全表扫当常态查询慢时先看计划不要盲加索引。isql里SET PLAN ON打开计划输出再执行查询看它是走索引还是全表扫。LIKE %A%这种前后通配不会走普通索引LIKE A%前缀匹配才有机会低选择性字段建索引反而拖慢写入。SET PLAN ON; SELECT ID, NAME FROM CUSTOMER WHERE NAME Customer-A; CREATE INDEX IDX_CUSTOMER_NAME ON CUSTOMER (NAME); COMMIT;SET PLAN ON只影响当前isql会话CREATE INDEX后要COMMIT才生效。建完再跑一次同样的查询对比计划输出。索引不是越多越好更新频繁的表先看写入代价。我一般把“恢复演练 计划对比”作为改源码前的固定动作从那以后每次拿到 InterBase 6.0 的包都先跑一遍空库恢复和计划检查再动一行代码。希望帮到你。本文还有配套的精品资源点击获取