
简介面向Delphi 5至Delphi 2009开发者的Oracle Data Access ComponentsODACv6.80.0.47 FS版本是一套完整的Oracle数据库访问组件方案包含TOracleConnection、TOracleQuery、TOracleTable等常用组件可帮助开发者快速构建稳定高效的数据库应用。包体共1794个文件、约6.11MB以pas源代码、dfm窗体、dpk包、res资源等为主同时提供Demos示例、Help文档、DBToolsInterfaces接口定义及Source源码目录覆盖从入门实践到底层原理的完整链路。已有280人学习下载适合正在使用Delphi构建Oracle项目的初中级开发者也适合维护老版本Delphi工程的技术人员。压缩包内附Make.bat等构建脚本以及WebForm.aspx、Global.asax等Web/服务端演示程序便于快速验证组件连接与配置完整源码和工程文件可支撑二次开发与深度定制是学习ODAC组件机制和解决实际集成问题的实用资料。1. 项目概述为什么还在用ODAC 6.80连接Oracle在Delphi生态里Oracle.Data.Access.ComponentsODAC算得上是一个老朋友了。我第一次接触这个组件库还是在学校实验室做数据库课设的时候指导老师扔给我一个压缩包就是类似ODAC v6.80.0.47这种带版本号的rar文件让我自己去搞定Oracle连接。当时年少无知以为直接用ADO连Oracle就行结果踩了一路的坑。后来才明白在Delphi 5到Delphi 2009这个年代ODAC几乎是衔接这两套技术栈最可靠的一座桥。这版v6.80.0.47从版本号就能看出是6.80系列的一个维护版本对应支持的是Delphi 5到Delphi 2009这一个跨度极大的编译器版本区间。很多人会问都2025年了还在研究这一个古董组件包有什么意义但现实是很多企业级老系统就是用Delphi 7或者Delphi 2007写出来的数据库后端是Oracle 9i甚至Oracle 10g运行在Windows Server 2003或XP上。这些系统不是不换而是不能随便换业务逻辑太重测试成本太高所以它们大概率还要再战五年甚至更久。只要这些系统还在跑ODAC就始终有一批忠实的受众。这篇文章不打算写成官方手册的翻译稿而是从实际项目部署和开发的角度讲讲ODAC v6.80.0.47这个版本怎么安装、怎么配置、怎么避坑以及在老项目里维护和升级Oracle连接时应该注意哪些细节。适合刚接手老项目的Delphi开发者也适合那些在维护遗留系统时被迫跟Oracle和ODAC打交道的朋友。2. ODAC核心组件与选型思路2.1 ODAC到底是一套什么东西ODAC的全称是Oracle Data Access Components由Devart公司开发。它是一组专门用于Delphi和C Builder环境下以原生方式访问Oracle数据库的VCL控件。和微软的ADO组件不同ODAC不依赖OLE DB或ODBC这种中间层而是直接通过Oracle Call InterfaceOCI与数据库通信。这意味着它绕开了很多中间翻译环节在性能上尤其是大批量数据操作时优势非常明显。v6.80.0.47这个版本内部包含了多个核心单元比较常见的有TOraSession连接会话组件负责管理数据库连接、事务和会话参数相当于ADO里的TADOConnectionTOraQuery参数化查询组件用于执行SQL语句和存储过程是日常开发中使用频率最高的组件TOraTable直接映射数据库表或视图的组件适合快速开发简单的增删改查界面TOraDataSource数据源组件连接数据集组件和DBGrid等可视化控件起到桥接作用TOraScript批量执行SQL脚本适合做数据库初始化和升级脚本TOraLoader把外部数据文件快速导入Oracle表的工具组件类似SQL*Loader的客户端版TOraSQL执行不返回结果集的SQL命令适合DDL和DML操作TOraStoredProc调用Oracle存储过程。从组件覆盖面来说这一套并不比当时的ADO组件少。而且因为走了OCITOraQuery在处理Oracle特有的数据类型例如CLOB、BLOB、TIMESTAMP、XMLType时比ADO的表现稳定得多。尤其在实际项目里处理中文和复杂日期类型时ODAC的字段映射方式更接近Oracle原生行为出问题的概率显著降低。2.2 为什么在D5到D2009年代更倾向于用ODAC而不是ADO在很多项目里数据库这一层选型往往就是团队内部吵出来的结果。我见过不少团队最初用ADO连接Oracle觉得“微软的东西嘛兼容性肯定好”。但做了一段时间以后问题就开始暴露了。首先是性能损耗。ADO连接Oracle通常走的是Microsoft OLE DB Provider for Oracle或者ODBC驱动。这两条路径本质上都是将OLE DB/ODBC调用转换成OCI调用中间隔了一层意味着每次数据访问都要经过额外的转换处理。在数据量小的时候感觉不出来一旦涉及十万级以上的数据遍历或者多表关联查询响应时间的差异就很明显。其次是类型映射的问题。ADO驱动在映射Oracle的NUMBER类型时往往会转成DBML或整数类型而ODAC可以让你精确控制映射成Smallint、Integer、Float还是BCD这对于金融和统计类应用是极其重要的。还有Oracle的DATE类型ADO读出来经常带有时区偏移或者格式不一致的问题而ODAC的TOraSession里可以通过会话参数直接控制日期格式一套代码在测试库和生产库之间切换时不用改SQL。再一个就是部署复杂度。用ADO方案时目标机器上必须正确安装并注册OLE DB Provider或ODBC驱动还要配置数据源名称或者连接字符串。对于老式Windows系统这一步经常因为权限和注册表问题卡壳。而ODAC的OCI直连方式只要目标机器有Oracle客户端或者Instant Client配好TNSNAMES.ORA代码里写清楚连接参数基本就能跑起来省了一堆系统配置的麻烦。当然ODAC也不是没有缺点。它是商业控件早期版本有授权文件的限制每年都要续期而且公司内部如果购买的是源码版本升级Delphi版本时还得重新编译一遍源码包。但对于那些“稳定第一、性能优先”的数据库类应用来说ODAC带给你的收益通常会大于它在授权和维护上的成本。2.3 版本选择v6.80.0.47适合什么场景每次提到老版本ODAC都有人问“为什么不用最新版”。这里得分场景看待。如果你维护的是一个从2010年以前就存在的项目编译器还是D7或D2007那升级整套ODAC到新版本反而可能引入不兼容问题。ODAC v6.80.0.47算是6.x系列里比较稳定的一个版本。它支持Oracle 9i到Oracle 11g的客户端版本这在同时期的老项目中足够用了。即使你现在的数据库已经升级到了Oracle 19c只要Oracle客户端版本与服务器兼容ODAC 6.80在连接协议上仍然能正常工作。在我维护的一个老项目中就出现过用ODAC 6.80.0.47配32位Oracle 11g客户端成功连接19c数据库的先例因为Oracle本身的客户端—服务器版本兼容策略做得比较宽。所以说选择这个版本的ODAC并不是因为它是功能最全的而是因为它在“老编译器 老系统 旧代码”这个组合里的稳定性是经过长期验证的。如果项目本身运行正常没有非要迁移不可的理由不要轻易折腾数据库访问层。3. 安装部署与版本适配详解3.1 安装前的环境检查清单在真正把ODAC安装到IDE之前我建议你先花五分钟确认环境情况否则很容易出现安装百分之八九十时报错然后又要卸载重来的情况。你需要检查这几项Delphi具体版本ODAC安装包通常会区分“Delphi 5”“Delphi 6”“Delphi 7”“Delphi 2005/2006/2007/2009”等不同选项。注意Delphi 2009和Delphi 2010不是一回事不要选错。Oracle客户端是否存在ODAC运行时依赖OCIOracle Call Interface也就是Oracle客户端或Instant Client。确认机器上安装了合适的客户端并且PATH环境变量里能看到oci.dll所在目录。权限问题在Windows 7及以后的操作系统上安装控件包需要管理员权限。右键以管理员身份运行安装程序可以避免很多奇怪的权限报错。备份IDE配置安装控件包有时会修改IDE的Library路径和已安装组件列表。为了避免万一装坏影响进度建议提前导出当前IDE配置或者至少记住自己原来配置了哪些第三方控件。检查完这些之后再打开压缩包里的安装程序。一般正规的安装包会包含多个子目录比如Source、Lib、CBuilder、Delphi等对应不同编译器和开发环境。3.2 Delphi各版本安装路径差异现在假设你已经在运行安装程序选择对应版本时系统会提示你选择“Install”或者“Compile”。我刚接触这类组件时总喜欢选“Compile”模式觉得从源码编译更放心。但后来发现如果只想快速用起来选择“Install”模式直接安装预编译好的包才是最高效的特别是Delphi 2009这种编译器比较特殊的版本从源码编译时经常会遇到动态包和静态链接选项不一致导致的错误。对于Delphi 5和Delphi 6这类老编译器建议把组件安装到原目录而不是自定义目录。因为老版本IDE对长路径和特殊字符的支持不好路径一旦带空格或者中文字符编译Link阶段会报一些莫名其妙的问题。Delphi 2007和Delphi 2009是VCL和RTL发生较大转变的版本Unicode支持从2009开始引入。ODAC 6.80.0.47是为数不多能同时兼容Delphi 7的AnsiString时代和Delphi 2009的Unicode时代的组件包。在2009下安装时如果IDE提示“Package ... has not been compiled with the current compiler”不要慌这说明你选错包版本了退出重新选择对应D2009的包即可。3.3 Oracle客户端和TNS配置ODAC本身不包含Oracle客户端它只是把OCI的接口封装成VCL组件。所以你机器上必须能通过SQL*Plus或者PL/SQL Developer连上目标数据库ODAC才有用武之地。TNSNAMES.ORA文件的位置在%ORACLE_HOME%\network\admin下里面定义的是网络服务名。ODAC连接Oracle时需要在TOraSession的Server属性里填这个网络服务名而不是直接填数据库实例名。很多新手在这里卡住明明数据库就在本机填了SID却连不上就是因为忽略了TNSNAMES.ORA的配置。如果你不想用TNSNAMES.ORAODAC也支持在Server属性里直接写host:port:sid的格式例如192.168.1.100:1521:ORCL这种写法在排场环境里很有用因为不需要每台客户端机器都去配TNS文件。还有一招是直接写Easy Connect字符串比如192.168.1.100:1521/ORCL两种写法在ODAC里基本等价重点是冒号和斜杠不要写错。4. 实操连接Oracle并跑通第一个查询4.1 基础连接配置与TOraSession设置在窗体上放一个TOraSession、一个TOraQuery、一个TOraDataSource和一个DBGrid这是最经典的组合。双击TOraSession打开连接参数窗体可以看到很多选项但最关键的就三个Server填写TNSNAMES.ORA里的网络服务名或者直接写主机:端口:SIDUserNameOracle用户名Password对应密码。还有一个容易被忽略的Options选项卡里面有个Direct模式。勾选Direct以后ODAC会绕过Oracle客户端直接以TCP协议去连数据库。这样做的好处是客户端不需要安装Oracle客户端但缺点是功能受限比如不能调用某些高级特性而且不同Oracle版本对协议的兼容性要求比较苛刻。我的建议是能用客户端就尽量用客户端Direct模式只适合测试或临时应急。设置完这些以后调用OraSession.Connected : True连接就建立了。第一次连接成功后建议你在AfterConnect事件里打印一下OraSession.ServerVersion确认连上的是你预期中的数据库版本避免开发库和生产库混用导致数据写错。4.2 常用组件用法与参数绑定TOraQuery是ODAC里最核心的数据访问组件它的SQL属性里可以直接写查询语句OraQuery1.SQL.Text : SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO :DEPTNO; OraQuery1.ParamByName(DEPTNO).AsInteger : 10; OraQuery1.Open;注意这里的参数名前面要加冒号这是Oracle SQL的标准写法。ODAC对参数绑定的支持非常完善Params的Value类型可以直接赋成TDateTime、Integer、String等它会自动转换。比如查询最近七天的订单可以直接写OraQuery1.SQL.Text : SELECT * FROM ORDERS WHERE ORDER_DATE :START_DATE; OraQuery1.ParamByName(START_DATE).AsDateTime : IncDay(Now, -7); OraQuery1.Open;ODAC在绑定日期类型时会自动处理Oracle DATE和TIMESTAMP的差异这比拼字符串要稳妥得多。说句实在话我见过太多生产事故就是因为在SQL里拼日期字符串遇到格式不一致时要么查不到数据要么报了ORA-01843。存储过程的调用也很直观。假设Oracle里有个存储过程P_GET_EMPLOYEE_COUNT返回一个输出参数你可以这样写OraStoredProc1.StoredProcName : P_GET_EMPLOYEE_COUNT; OraStoredProc1.ParamByName(P_DEPTNO).AsInteger : 20; OraStoredProc1.ExecProc; ShowMessage(OraStoredProc1.ParamByName(P_COUNT).AsString);这里的核心是ParamByName里的名字要跟Oracle存储过程的参数名一一对应大小写不敏感但拼写不能错。4.3 事务处理与批量更新技巧ODAC的事务控制是在TOraSession上做的默认启用了隐式事务。大多数情况下写操作会自动提交但当你需要保证多项数据操作的一致性时就要显式控制事务边界OraSession1.StartTransaction; try OraQuery1.SQL.Text : UPDATE ACCOUNT SET BALANCE BALANCE - 100 WHERE ID 1; OraQuery1.ExecSQL; OraQuery1.SQL.Text : UPDATE ACCOUNT SET BALANCE BALANCE 100 WHERE ID 2; OraQuery1.ExecSQL; OraSession1.Commit; except OraSession1.Rollback; raise; end;这里有个经验如果批量插入几千行数据不要一行一个Commit那样性能极差。应该开启一个事务攒够一定量再Commit一次比如每500行提交一次能显著提升速度。如果数据量达到几万行强烈建议改用TOraLoader组件它是专门为大数据量导入设计的效率比逐行ExecSQL高出一个数量级。5. 常见问题与排查技巧实录5.1 连接报错“ORA-12154: TNS: 无法解析指定的连接标识符”这个错误在ODAC连接中最常见十个人里至少有八个人遇到过。通常的原因是Server属性里填写的网络服务名在TNSNAMES.ORA里找不到。排查思路很简单先用SQL*Plus试一下同样的连接串看能不能连上确认TNSNAMES.ORA文件路径是否正确。可以用环境变量TNS_ADMIN指定目录确认TOraSession的Server属性与TNSNAMES.ORA里的网络服务名是否完全一致包括大小写和有没有多余空格。有一种隐蔽情况是机器上装了多个Oracle客户端ODAC加载OCI时找到的未必是你配置TNS的那个客户端。这时候需要查看PATH顺序或者把不需要的客户端从路径里临时移除。5.2 字符集乱码的排查路径Delphi 2009以前是AnsiString时代Delphi 2009以后是Unicode时代。ODAC 6.80.0.47同时兼容这两个时代但也因此牵扯出字符串编码的混乱问题。核心解决思路是让ODAC的会话字符集和数据库字符集保持一致。在TOraSession的Options里有一个Charset属性。当数据库字符集是AL32UTF8时在Delphi 2009里把这个值设置成AL32UTF8能让字段读写直接以Unicode方式处理避免乱码。比较头疼的是老项目里数据库字符集是ZHS16GBK的情况。在Delphi 7里AnsiString的默认代码页是GB2312CP936所以如果ODAC的Charset设置为空或者和数据库一致通常能够正常显示中文。但一旦项目升级到Delphi 2009代码页变成Unicode而数据库又是GBK你就需要让ODAC显式把字符集转换成UTF8或Unicode然后在应用层再转换一次。这个转换在ODAC里是通过设置OraSession.Options.Charset和UseUnicode这两个参数协同完成的。简单的经验是数据库字符集是UTF8Delphi 2009则设置UseUnicode : TrueCharset : AL32UTF8数据库字符集是GBKDelphi 7则设置Charset : UseUnicode : False数据库字符集是GBKDelphi 2009则设置UseUnicode : TrueCharset : ZHS16GBK让ODAC做转换。5.3 64位程序编译与运行问题ODAC 6.80时代还没有原生的64位版本当时编译出来的程序都是32位。如果你在64位Windows上运行程序会以WoW64模式执行此时必须安装32位的Oracle客户端不能直接使用64位的Oracle客户端。这个坑我踩过不止一次。曾经在生产服务器上只装了64位Oracle客户端运行老程序时直接报“ORA-12154”或“无法定位OCI动态链接库”查了半天最后发现是32位程序找不到64位客户端的OCI资源。解决方法是到Oracle官网下载32位的Instant Client解压后把目录加到PATH里并确保应用的当前工作目录没有残留的oci.dll文件因为Windows加载DLL时优先加载程序目录下的同名文件。如果程序本身是编译成64位的那就不能用ODAC 6.80了。需要选择后来的ODAC版本或改用其他数据访问方案。这也是很多老项目宁愿继续用32位编译的原因之一。5.4 高版本Oracle连接中的认证与加密问题还记得前面提到的老项目用ODAC 6.80连接Oracle 19c吗那个案例里Oracle连接时默认采用SQL*Net加密和认证机制。当客户端是11g、服务器是19c时可能在首次连接时报出“ORA-28040: No matching authentication protocol”之类的错误。解决这个问题有两种常规思路。一种是修改Oracle服务器的SQLNET.ORA文件把SQLNET.ALLOWED_LOGON_VERSION_CLIENT调整到一个兼容的低版本比如8。但这种方法在生产环境往往不好实施因为安全策略不允许降低标准。另一种是更新Oracle Instant Client到与服务器接近的版本比如19c客户端然后重新配置ODAC的OCI路径。ODAC通过OCI和数据库通信所以只要OCI足够新认证协议的兼容性也就自然解决了。5.5 常见问题速查表问题现象可能原因排查/解决方向ORA-12154TNSNAMES.ORA未找到或Server名称写错检查TNS_ADMIN路径和Server属性ORA-12514监听器无法识别服务名确认数据库服务名和监听配置ORA-01017用户名/密码无效核对数据库账号和权限ORA-28040认证协议版本不匹配升级Instant Client或调整SQLNET.ORA中文乱码字符集不匹配设置OraSession.Options.Charset和UseUnicode缺少OCI找不到oci.dll确认32/64位客户端匹配并配置PATH包未安装成功Delphi版本选错退出安装程序选择对应版本包重新安装连接以后程序退出报错Oracle客户端版本过旧更新Instant Client到兼容版本6. 老项目升级与后续维护思考6.1 从D7迁移到D2009及以上版本时的注意点老项目如果正打算从Delphi 7迁移到Delphi 2009会发现最痛苦的就是字符串编码问题。D7时代用PChar、String直接对指针和字符数组操作的大量代码在Unicode版本里经常会报类型不匹配或者长度计算错误。ODAC在这类迁移中扮演的角色是让数据库访问层尽量不用改代码。因为ODAC 6.80.0.47能够同时支持D7和D2009你只需要在D2009里重新编译一下包然后把业务代码里涉及数据库字段读取的地方检查一遍把string和AnsiString的赋值关系理清楚就行。在数据库层如果原来存取的字段是VARCHAR2或NVARCHAR2类型映射不会有太大变化。但迁移之前强烈建议用代码对比工具先把改动范围摸清楚评估数据访问层到底有多少地方直接操作了Bytes或PChar。很多看似简单的字段读取在Unicode模式下语义完全不一样了比如Length(str)以前是字节数现在变成了字符数导致在旧代码里截断字段值的逻辑全盘失效。这类坑不是ODAC引起的但会在你迁移数据库访问代码时碰到提前有个心理预期。6.2 维护老系统的几个实用习惯维护带ODAC的老项目我觉得最值得养成的习惯是做好数据库连接信息的集中配置。很多老代码喜欢把TNS连接串直接写在代码里一旦换了测试库或者生产库就得改代码重新编译非常痛苦。推荐的做法是在程序启动时从外部配置文件读取连接参数赋值给TOraSession。比如有一个CONFIG.INI文件[Database] Server192.168.1.100:1521/ORCL UserNameapp_user Password******然后在主窗体的FormCreate里OraSession1.Server : IniReadString(Database, Server, ); OraSession1.UserName : IniReadString(Database, UserName, ); OraSession1.Password : IniReadString(Database, Password, );这样无论是换库还是换密码运维人员只需要改配置文件不需要重新编译程序。这个习惯在维护阶段能省下大量沟通成本。再有一个经验是数据库连接要加心跳检测。Oracle长时间空闲的连接会被防火墙或数据库端断掉这个时候客户端的连接池其实已经失效了下次执行查询会报“ORA-03113: end-of-file on communication channel”。ODAC里可以在TOraSession的OnError事件里捕获这个错误然后自动重连或者定时执行一个简单的SELECT 1 FROM DUAL来保活连接。6.3 从ODAC到其他数据访问方案的迁移路径虽然ODAC很好用但在新项目里我不太建议再选择这么老的方案。假如你正在接手一个老项目而且终于下定决心要摆脱Oracle客户端依赖可以考虑几个替代方向。第一FireDAC。这是Delphi XE5以后内置的一套数据访问组件也支持Oracle直连而且有原生的64位支持已经成了新项目的默认选择。如果项目准备升级到较新的Delphi版本FireDAC是最自然的迁移目标。第二直接使用Oracle官方提供的Oracle Data Provider for .NET但那是给C#和VB.NET用的跟Delphi不搭界。第三将数据访问层封装成REST API前端Delphi程序只负责调用HTTP接口。这样数据库迁移也好、跨平台也好影响面都被限制在服务端。这种方案适合业务逻辑相对集中、可以接受异步交互的项目。迁移是大事通常要结合业务系统的稳定性要求和团队的技术储备来定不能因为某组件老就一刀切。我见过Delphi 7 ODAC的POS收银系统在门店跑了十几年依然稳定的案例也见过项目刚上线就因数据库访问层切换得太激进导致故障频出。所以迁移的原则应该是系统在原有环境下能稳定运行、业务没有新需求就先别折腾真到了要动数据访问层的那一天优先考虑平滑过渡。写在最后的一些体会我始终觉得工具链的新旧并不等于能力的强弱老技术如果被用在了它适合的位置反而比盲目上新方案更可靠。ODAC 6.80.0.47这样的组件包放在今天已经算是古董中的古董了但它支撑了大量Delphi老项目的日常运转让那些写于十多年前的业务代码依然在数据库和界面之间忙碌地搬运数据这本身就是一种价值。如果你也是因为维护老系统而接触ODAC希望这篇文章能帮你少走一点弯路。数据库连接不是最难的部分真正难的是在时间和资源都有限的前提下不让老系统成为团队的负担。把连接配置管理好、把字符集问题理顺、把常见的ORA报错摸清你就能在这个旧世界里过得比大多数人轻松。最后分享一个小技巧吧拿到安装包后第一时间去压缩包里查看Docs目录下有没有对应版本的帮助文档很多老工具包会把最关键的参数说明放在PDF或CHM文件里。我当年就是靠着ODAC自带的帮助文档才把TOraSession里那几十个属性挨个弄明白的。别看网络上的回答铺天盖地很多时候最准确的答案就在那个不起眼的chm文件里。本文还有配套的精品资源点击获取