首页/新闻资讯/正文详情

IBDAC在Delphi 13.1中的安装配置与性能优化实战

发布时间:2026/9/25 2:18:36 来源:云帆数科 栏目:资讯中心
IBDAC在Delphi 13.1中的安装配置与性能优化实战
简介面向Delphi 6至13.1开发者的IBDAC v9.0.0组件包提供高效访问InterBase与Firebird数据库的完整方案覆盖数据增删改查、事务控制及存储过程、触发器调用适合桌面应用与RESTful服务场景。资源共2000个文件以pas源文件、dpk/dproj工程文件、hpp头文件、res资源与dfm窗体文件为主压缩包仅17.01MB结构完整便于按需取用。已有63人参与学习。值得强调的是包内含全套源代码开发者可深入理解组件机制并按业务定制扩展同时通过本地API交互显著提升性能支持InterBase存储过程、触发器及Firebird高级数据类型内置事务管理满足复杂业务逻辑并支持异步操作和RESTful API暴露便于构建现代数据服务。配套文档与示例代码能降低入门门槛对需要深度集成InterBase/Firebird的Delphi团队而言它兼具实用性与可读性。1. 组件装了不叫会用IBDAC 在 Delphi 13.1 里到底解决了什么很多用 Delphi 做 InterBase 或 Firebird 开发的人第一反应是「用自带的 BDE 或者 DBX 不就行了」。但等你在 Delphi 13.1 里真正接入 Firebird 3.0 或者 InterBase 2020 之后会发现 BDE 早就被淘汰DBX 对 Firebird 的新特性支持也跟不上尤其是布尔类型、窗口函数、生成列这些。IBDACInterBase and Firebird Data Access Components是 Devart 做的一套原生驱动组件v9.0.0 这一版同时覆盖 Delphi 6 到 Delphi 13.1核心价值是让你不用装任何额外客户端直接用动态库连上 InterBase 和 Firebird并且把事务、批量提交、缓存更新这些细节封装成组件。这篇文章不是让你照着装完就关掉而是把从选型、安装、写代码到排错的一条完整路径讲清楚。2. 组件分层与选型先把 TIBCCustomQuery 和数据源的关系理清2.1 IBDAC 的单元命名与连接组件 TIBCCustomConnectionIBDAC 在安装完之后IDE 的组件面板上会出现一组以 TIBC 开头的组件。你会在 Tool Palette 里看到 TIBCConnection、TIBCTransaction、TIBCCustomQuery、TIBCQuery、TIBCTable、TIBCStoredProc、TIBCDataSource、TIBCUpdateSQL 等。第一次看到这些名字容易误以为它们和 DBX 一样是「连接、查询、数据源」的三层结构。其实 IBDAC 的分层更贴近 InterBase 的原生 API。TIBCConnection 是基础连接组件它负责持有数据库连接句柄管理服务器的版本信息、字符集设置、登录参数。它不像 ADOConnection 那样本身带 Recordset也不像 FireDAC 的 TFDConnection 那样直接可以执行 SQL。在 IBDAC 里连接只是一个通道真正干活的是查询组件而查询组件要靠 TIBCTransaction 来绑定事务上下文。我通常建议第一次接触 IBDAC 的人先不用急着写业务代码而是把 TIBCConnection、TIBCQuery、TIBCTransaction、TIBCDataSource 这四个拖到窗体上按顺序把属性串起来。串起来的逻辑是TIBCConnection 指定连到哪个服务器和数据库TIBCTransaction 关联同一个 Connection并决定隔离级别TIBCQuery 的 Connection 属性填 TIBCConnectionTransaction 属性填 TIBCTransaction最后 TIBCQuery 的输出通过 TIBCCustomQuery 的 DataSource 属性或者直接绑定给数据感知控件。2.2 为什么在 Delphi 13.1 里选 IBDAC 而不是 FireDACDelphi 自带的 FireDAC 也支持 InterBase 和 Firebird而且免费。但 IBDAC 有一个实际场景上的优势兼容的 Delphi 版本跨度大。很多老项目还跑在 Delphi 6 或 Delphi 7 上同时新项目又要用 Delphi 13.1如果团队想用同一套数据访问代码IBDAC 是少数能做到从 Delphi 6 到 Delphi 13.1 都保持 API 一致的商业组件。FireDAC 是哪个 Delphi 版本才引入的Delphi 2009 之前的项目根本没法用。另一个选型理由是 Firebird 的方言支持。IBDAC 对 Firebird 3 和 InterBase 2020 的布尔值、数组字段、FB 的 EXECUTE BLOCK 和生成列都做了显式映射而 DBX 的老驱动对这些类型经常只返回字符串导致你写好的业务逻辑拿到 Delphi 里变成字符串比对排查起来非常烧脑。IBDAC 的数据类型映射可以直接在 TIBCCustomQuery 的字段类型上看到比如 TBooleanField 和 TFMTBCDField 会按原生类型呈现这就省去了手动转换的代码。需要注意IBDAC 不是免费的。v9.0.0 的安装包里通常会区分 Trial 和 FullTrial 版有连接时间限制而且会弹出提示窗口。如果你只是在学习阶段用 Trial 够了但如果要部署到生产环境必须购买授权。我见过有人用破解版最后在客户现场发生随机断开这种问题没法支持所以劝你直接走正规授权。2.3 TIBCCustomQuery 和 TIBCQuery 的区别TIBCCustomQuery 是一个抽象层你不能直接放到窗体上使用它在设计期没有图标只是用来派生新组件的基类。TIBCQuery 是它最常见的实现用来执行返回结果集的 SELECT 语句。TIBCQuery 还有一个重要特性就是它的 SQL 属性可以写多条语句IBDAC 支持用分号分隔这在 Firebird 的存储过程调试里特别有用。实际工作中我会用 TIBCQuery 来跑所有 SELECT用 TIBCTable 来处理单表简单操作用 TIBCTable 时它有一个 TableName 属性选好表之后就能直接绑定数据源不用写 SQL。但 TIBCTable 在多表查询上很吃亏因为它本质上是 SELECT * FROM 某张表所以遇到连接查询还是回到 TIBCQuery。3. 在 Delphi 13.1 中安装 IBDAC v9.0.0从 IDE 菜单到动态库落地的完整流程3.1 安装前需要确认的编译器与平台目标IBDAC v9.0.0 声称支持 Delphi 6 到 Delphi 13.1但这里有个隐藏坑它并不是一个安装程序装完就万事大吉而是需要借助 Devart 的 Installer 工具或手动添加源码路径。在 Delphi 13.1也就是 RAD Studio 的 13.1 版本里默认编译器是 Win32 和 Win64。IBDAC 的安装包里有独立的二进制文件分别对应不同编译器版本。我的步骤是先确认你的 Delphi 13.1 的安装目录里有没有$(BDSCOMMONDIR)\Components这个路径。一般你可以在 IDE 的 Tools Options Environment Variables 里看到 BDSCOMMONDIR 的值。IBDAC 会建议把组件安装到 Delphi 的默认组件目录但如果你像我一样用第三方组件管理工具也可以手动把Source和Lib目录加进 Library Path。千万别直接复制整个 IBDAC 目录到 Delphi 的 library 目录里那样会污染全局路径导致其他项目编译时找不到其他组件。另一个要确认的是目标平台。如果你只做 Win32 开发安装时选择 Win32 二进制如果要 Win64必须选择对应的 .dcu 文件。常见错误是只装了 Win32然后在 Delphi 13.1 里用 Win64 编译工程报错 Cannot find unit IBDAC 相关单元。这个后面会专门说。3.2 安装命令与 IDE 组件注册操作具体安装过程我以最常见的 Installer 模式描述。双击 IBDAC 安装程序选择 Delphi 13.1 对应的选项。安装完成后打开 Delphi 13.1点击 Component Install Packages在列表中找到 Devart IBDAC 相关的包确认处于勾选状态。如果没看到需要手动添加.bpl文件它一般在 IBDAC 安装目录的bin文件夹下比如dclIbDAC130.bpl版本号可能随编译器变化以你安装包中的实际文件名为准。如果你的 IBDAC 是源码版那就需要编译包。步骤如下// 打开 IDEFile Open选择 Delphi 13.1 对应的运行时包项目文件 // 例如 ibdac_d13.bpl 或类似命名以安装包实际文件为准 // 右键 Project Manager 中的项目选择 Compile再选择 Install编译完成后在组件面板的 Data Access 或 Devart 页签下你应该能看到以 TIBC 开头的组件。如果看不到检查当前项目的 Target Platforms 是否和已安装的包一致。比如说你在 IDE 里打开的工程是 Win64但安装的包是 Win32组件面板可能不显示因为 IDE 的组件设计期只加载匹配的包。3.3 最小连接验证拖一个按钮跑通 InterBase装完之后先别急着写业务先做一个最小验证确认驱动能连上。我在窗体上放一个 TIBCCustomConnection实际是 TIBCConnection和一个 Button然后在 Button 的 OnClick 里写procedure TForm1.Button1Click(Sender: TObject); begin IBDatabase1.Server : 127.0.0.1; IBDatabase1.Port : 3050; IBDatabase1.Database : C:\Data\employee.fdb; IBDatabase1.UserName : sysdba; IBDatabase1.Password : masterkey; IBDatabase1.Protocol : TCP; IBDatabase1.CharSet : UTF8; IBDatabase1.Connected : True; ShowMessage(连接成功); end;说明这里的IBDatabase1是 TIBCConnection 的默认名字如果你没改名的话。Protocol可选 TCP、NetBEUI、SPX 等现代开发只用 TCP。CharSet我写了 UTF8如果你连接的是老 InterBase 数据库可能数据库本身是 NONE 字符集这时先别设 UTF8否则会报字符集转换错误。连接成功后再考虑字符集映射。这段代码不需要LoginDialog之类的属性IBDAC 在Connected : True时如果属性为空会直接使用这些赋值。如果连接失败会抛出异常你可以用try...except捕获打印出Exception.Message看具体错误码。4. 把 IBDAC 用起来连接串、事务和参数化查询的标准写法4.1 连接参数的最佳实践不要把用户名密码写死在代码里TIBCConnection 除了用属性赋值也支持用 ConnectionString 一次性设置。常见写法是with IBDatabase1 do begin ConnectionString : Server127.0.0.1;Port3050;DatabaseC:\Data\employee.fdb; User Namesysdba;Passwordmasterkey;ProtocolTCP;CharSetUTF8;; Connected : True; end;这里最容易踩坑的参数是Database。在 InterBase 和 Firebird 里这个路径是服务器端看到的路径而不是客户端的路径。如果你在 Windows 开发机上用绝对路径但在 Linux 服务器上部署 Firebird路径分隔符和盘符可能完全不同。解决方式是使用别名或者让 DBA 把数据库文件放在服务器本地然后在database参数里用服务器本地路径。CharSet参数建议显式设置不要依赖默认的 NONE。因为 InterBase 的老数据库如果没定义字符集插入中文时会出现 malformed string 错误。比较稳妥的做法是统一使用UTF8。但要强调这要求数据库本身能接受 UTF8 编码如果你的数据库是用WIN1252建的强行用 UTF8 连接会导致长度计算异常反而出现截断。这时候应该先用gbk或WIN1252然后在查询结果里手工转换。另一个参数是SQLDialect。InterBase 和 Firebird 支持方言 1 和方言 3。方言 3 完整支持现代 SQL 和数据类型方言 1 主要是兼容老应用。IBDAC 在连接时可以设置SQLDialect : 3但如果你的数据库实际上是用方言 1 创建的某些语句可能报错。开发前先用SELECT RDB$SETTING_DIALECT这种系统查询确认数据库的实际方言再设置连接参数否则会出现日期字段处理异常。4.2 事务绑定TIBCTransaction 的隔离级别和提交时机IBDAC 不允许查询组件在没有事务的情况下执行。每个 TIBCQuery 或 TIBCTable 都要绑定一个 TIBCTransaction。这个设计一开始让人不习惯但它保证了数据一致性。TIBCTransaction 的IsolationLevel属性默认是ReadCommitted我建议大多数 OLTP 场景保留这个值。Serializable级别虽然能避免幻读但锁粒度大在高并发时会导致大量等待和死锁。一个常见问题是多个查询组件共用同一个 TIBCTransaction当一个查询修改了数据另一个查询在同一个事务里读会看到什么这取决于 Firebird 的多版本并发控制机制。IBDAC 里只要TIBCTransaction.Active为 True同一个事务中的多个查询共享同一个快照。所以如果你在事务 A 中插入了一行还没提交事务 B 是看不到的。这其实是正确行为但很多人会误以为事务没提交就能在同一连接上读到然后排错半天。事务的提交和回滚代码很简单IBTransaction1.StartTransaction; try with IBQuery1 do begin SQL.Text : INSERT INTO EMPLOYEE (ID, NAME) VALUES (:ID, :NAME); ParamByName(ID).AsInteger : 1001; ParamByName(NAME).AsString : 赵工; ExecSQL; end; IBTransaction1.Commit; except IBTransaction1.Rollback; raise; end;逻辑说明StartTransaction要在查询执行前调用否则 IBDAC 会抛出 Transaction is not active 异常。ExecSQL只执行不返回结果集主要用于 INSERT、UPDATE、DELETE。如果你执行了 SELECT就用Open。提交前如果发生任何异常Rollback会把数据回滚然后raise把异常继续抛给上层通知用户。参数说明ParamByName是参数化查询的标准方式避免拼接字符串。注意Firebird 的参数占位符是冒号但 IBDAC 内部也支持?占位不过用命名参数更可读。参数类型不一定要显式指定IBDAC 会根据绑定值的类型自动推断但在极少数情况下如果参数用在LIKE子句里并且你传入的是AsString会遇到隐式类型转换问题。解决方法是显式设置DataTypeParamByName(NAME).DataType : ftString; ParamByName(NAME).AsString : % Edit1.Text %;4.3 参数化动态 SQL三种常用写法及适用场景业务系统里动态条件查询是最常见的需求。IBDAC 支持三种写法直接用 TIBCCustomQuery 的 SQL.Text 拼接用Macro机制动态替换整段 SQL以及用参数化条件。第一种写法很直接但要小心注入风险。如果条件是数字可以先StrToIntDef校验如果是字符串必须转义单引号。第二种写法是 IBDAC 的Macro功能它在 SQL 文本里用{MacroName}占位执行前通过MacroByName赋值。这个适合动态切换表名、排序字段这种无法参数化的地方with IBQuery1 do begin SQL.Text : SELECT * FROM { TableName } WHERE STATUS :STATUS ORDER BY { OrderBy }; MacroByName(TableName).AsString : EMPLOYEE; MacroByName(OrderBy).AsString : ID DESC; ParamByName(STATUS).AsInteger : 1; Open; end;注意Macro不能用来传值因为宏是直接替换进 SQL 的所以表名、列名、排序方向可以用但用户输入的值必须走Param。第三种写法就是标准参数不需要多说。有一个细节当使用Macro时如果在同一个查询组件里反复替换不同表名IBDAC 会因为解析缓存导致结果集结构不刷新。解决办法是执行前调用Prepare或直接重新给SQL.Text赋值。这算是一个隐藏坑后面在避坑章节细说。5. 避坑IBDAC 最容易翻车的 5 个常见问题与排查方法5.1 安装后 IDE 找不到 TIBCConnection 组件现象在 Delphi 13.1 的组件面板里翻遍了 Devart 页签只看到几个非 TIBC 的其他组件或者什么都没有。原因最常见的是安装时选了 Win32 的包但 IDE 当前启动的是 Win64 模式。Delphi 13.1 的 IDE 本身可以同时加载 32 位和 64 位组件包但有些版本对未签名的第三方包会静默跳过。另一个原因是.bpl没有成功注册到 IDE 的注册表中或者你在安装时取消了 Design-Time 包。解决先关掉 Delphi重新运行 IBDAC 安装程序选择 Repair 并确保勾选 Design-Time 组件。如果还不行手动打开 Component Install Packages点击 Add浏览到 IBDAC 安装目录下的dcl目录选择对应的.bpl。注意要选带dcl前缀的那是设计期包不带前缀的是运行时包。设计期包安装后组件才会出现在面板上。5.2 Firebird 3.0 之后连不上报 unavailable database 或 provider现象本地开发用 Firebird 2.5 时连接正常。换到 Firebird 4.0 或 InterBase 2020运行时提示 Error loading plugin provider 或 I/O error for file ... unavailable database。原因Firebird 3.0 改变了架构连接必须指定认证插件。IBDAC 连接时如果没带Server和Port以外的参数默认可能走老的 isc 机制而 Firebird 3.0 要求WireCrypt和AuthServer配置。另外客户端动态库fbclient.dll版本太旧或者没有放到可执行文件目录也会导致连不上。解决解决方式分两步。第一步在 IBDAC 的TIBCConnection上增加参数比如CanUseTransaction和UseUnicode但更关键的是在连接串中加ServerType。有些版本支持IBDAC专用参数比如ConnectionString : Server127.0.0.1;Port3050;DatabaseDB;User Namesysdba; Passwordmasterkey;ProtocolTCP;CharSetUTF8;ServerTypeFB30;第二步从 Firebird 官方发行版中复制对应编译位数的fbclient.dll比如 fbclient.dll 的 64 位版本放到 exe 同目录。注意IBDAC 默认会按顺序查找 gds32.dll、fbclient.dll 等如果没有找到会报 provider 错误。建议用TIBCCustomConnection的LibraryName属性直接指定动态库绝对路径IBDatabase1.LibraryName : C:\Firebird\fbclient.dll;这样能避免系统路径里有老版本干扰。5.3 查询卡住或锁表事务没提交导致的连锁问题现象在 Delphi 13.1 里执行一条 UPDATE 后程序不退出再次查询同一行数据就卡死一直等到超时报 lock conflict on no wait transaction。原因上一条事务开始后你执行了更新但没有执行Commit或Rollback事务一直处于活跃状态。此时事务持有的锁没有释放后续的查询和其他连接都在等这个锁。这在 IBDAC 里特别容易发生因为它的TIBCQuery.ExecSQL会隐式开始一个事务吗并不会它需要你显式绑定事务。但如果你绑定了事务却没提交问题就来了。解决严格执行事务生命周期。一个靠谱的模式是每个业务操作都封装在一个StartTransaction...Commit/Rollback里。另外可以利用 IBDAC 的TIBCQuery的Options属性中的AutoCommit和KeepConnection。如果你希望单条查询自动提交可以设置TIBCTransaction.AutoCommit : True。但这会把多条语句装进不同事务影响一致性。我的习惯是读操作使用只读事务写操作显式事务。只读事务可以设置TIBCTransaction.ReadOnly : True这样即使忘记提交也不容易造成锁等待。5.4 中文乱码字符集设置不一致的三个层级现象插入的中文数据在数据库工具里看是 ? 号或者从 Delphi 读出来变成乱码又或者写入时报 Malformed string。原因字符集问题有三个层级。第一层是数据库本身的字符集如果建库时没有设置CHARSET UTF8那字段默认是 NONE放入字节流时不校验编码。第二层是连接字符集如果连接用WIN1252而数据库是 UTF8写入时会转换错误。第三层是客户端显示组件的字符集。IBDAC 中TIBCConnection.CharSet只是告诉驱动「客户端发送什么样的编码」但它不会自动把旧数据转成 Unicode。解决建议统一使用 UTF8。首先要确认字段字符集。用 IBDAC 执行IBQuery1.SQL.Text : SELECT RDB$FIELD_NAME, RDB$CHARACTER_SET_NAME FROM RDB$FIELDS WHERE RDB$CHARACTER_SET_NAME IS NOT NULL;如果发现字段字符集是NONE需要先转换数据库字符集。Firebird 里可以用ALTER DATABASE SET DEFAULT CHARACTER SET UTF8但这只对新建对象生效已有字段仍需重建。在 IBDAC 里更实际的做法是先将CharSet设为NONE也就是不指定读取数据后用UTF8Decode手动转码。另外在 Delphi 13.1 中string 默认是 UTF-16如果你的字段是 UTF8IBDAC 会自动转成 Unicode。如果你看到乱码大概率是连接参数里的CharSet和字段实际字符集不一致。比如字段是WIN1252连接却设了UTF8驱动会把字段内容当成 UTF8 解码中文自然变成乱码。一个排查技巧把连接CharSet改为NONE如果乱码消失说明是转换方向搞反了。5.5 升级到 Delphi 13.1 后编译报 Cannot find unit现象项目从 Delphi 10.4 迁移到 Delphi 13.1打开工程后编译提示Cannot find unit TIBCQuery或Unit IBDACnot found。原因IBDAC v9.0.0 虽然支持 Delphi 13.1但你的项目搜索路径里可能还指向旧版本的源码或 .dcu 文件。Delphi 升级后旧版本组件的.dcu不能直接用可能会出现兼容性错误。另外一个原因是 IBDAC 安装到了某个地方但 IDE 的 Library Path 没有自动包含。解决打开 Project Options Delphi Compiler Search Path在列表里添加 IBDAC 的源文件路径通常是C:\Program Files\Devart\IBDAC\Source这种。注意不要只加 Source还要加对应平台和编译器版本的Lib\Win64或Lib\Win32目录那里存放编译好的.dcu。如果项目是 64 位而你只装了 64 位包确认Library Path里有 Win64 路径。还有一种情况是你把这个路径加到全局 Library Path 里但项目自己的 Search Path 覆盖了它导致编译顺序出问题。此时直接在项目 Search Path 里追加更保险。6. 把 IBDAC 的读写性能再往前推一步缓存更新与 Array DML 批量提交6.1 CacheUpdate 的正确使用姿势TIBCCustomQuery 有一个CacheUpdate属性默认是 False。当它为 True 时你对查询结果集做的修改不会立即写入数据库而是缓存在本地然后通过ApplyUpdates一次性提交。这个功能很适合多层架构或者当你需要先用数据集填充 UI、在用户点击保存时才统一落库。具体做法是将TIBCQuery的CacheUpdate设为 TrueUpdateObject属性连接一个TIBCCustomUpdateSQL组件。TIBCCustomUpdateSQL里需要写三条 SQLInsertSQL、ModifySQL、DeleteSQL。如果你不想手写可以在设计期右键TIBCQuery选择Update Options自动生成。然后保存时调用IBQuery1.ApplyUpdates; IBTransaction1.Commit;注意ApplyUpdates会把缓存的修改逐条通过 UpdateSQL 发送到数据库。如果数据量很大比如几千条它会一条一条执行性能比较差。这时候不如直接用数组 DML 批量提交。6.2 Array DML 批量提交从逐条循环到一条语句Firebird 和 InterBase 的 API 支持数组参数把多组参数一次性发给服务器。IBDAC 在ExecSQL时如果使用数组参数会自动开启 Array DML。先看传统写法在一个StartTransaction里循环插入 1 万条IBTransaction1.StartTransaction; try for i : 0 to 9999 do begin IBQuery1.SQL.Text : INSERT INTO LOG(ID, MSG) VALUES (:ID, :MSG); IBQuery1.ParamByName(ID).AsInteger : i; IBQuery1.ParamByName(MSG).AsString : test IntToStr(i); IBQuery1.ExecSQL; end; IBTransaction1.Commit; except IBTransaction1.Rollback; raise; end;这段代码在局域网内大约要 3~5 秒因为每条 INSERT 都有一次网络往返。改成 Array DMLIBQuery1.SQL.Text : INSERT INTO LOG(ID, MSG) VALUES (:ID, :MSG); IBQuery1.Params.ArraySize : 10000; for i : 0 to 9999 do begin IBQuery1.ParamByName(ID).Values[i] : i; IBQuery1.ParamByName(MSG).Values[i] : test IntToStr(i); end; IBTransaction1.StartTransaction; try IBQuery1.ExecSQL(True); // 参数 True 表示使用数组模式 IBTransaction1.Commit; except IBTransaction1.Rollback; raise; end;逻辑说明Params.ArraySize告诉 IBDAC 参数数组的长度。Values[i]是对数组元素赋值而不是AsInteger。执行时调用ExecSQL(True)触发批量执行。这里有个细节StartTransaction要在ExecSQL之前但是在给参数数组赋值之后。因为数组赋值只发生在内存中不需要事务。参数说明ArraySize设置多大合适如果太小比如 50体现不出性能提升如果太大比如 100 万可能会占用大量内存。我测试过 1 万条的场景推荐 1000 到 10000 之间。另外如果其中有参数值为字符串IBDAC 会为每个数组元素分配独立的缓冲内存占用是数组大小乘以字段长度所以 10 万条的大文本字段要谨慎。这个方案不仅适用于 INSERT也适用于 UPDATE。比如你需要按主键批量更新状态用 Array DML 可以做到一条语句更新一批避免逐条打开结果集。但要注意Array DML 不能在CacheUpdate打开的情况下使用文档里也没写实际运行时偶尔会互相干扰。我的原则是批量写入用 Array DML界面交互式修改用 CacheUpdate两者不要混在同一个查询组件上。6.3 用一个小函数验证批量提交的收益写一个简单的计时函数把两种模式的耗时打印出来心里就有底了。我用GetTickCount或者TStopwatch计时代码不复杂var sw: TStopwatch; begin sw : TStopwatch.StartNew; // 执行 Array DML 或循环插入 sw.Stop; ShowMessage(耗时(ms): sw.ElapsedMilliseconds.ToString); end;对比结果通常是 1 万条以内两种差别不明显超过 5 万条时Array DML 能快 5 到 10 倍。这不是玄学而是因为减少了网络往返和事务日志写入次数。如果你现在还在用 For 循环逐条 ExecSQL真的建议改成数组模式特别是做数据导入、日志采集这类功能时省下的时间够你多写几个模块了。最后说一个我自己的血泪经验以前我在导入 Excel 数据时为了加进度条每条插入后都调Application.ProcessMessages结果导入 3 万条用了快一分钟。后来改成 Array DML界面假死但总耗时只有 3 秒。进度条是给用户看的批量任务本身不需要逐条反馈你可以每 1000 条更新一次进度条用户体验反而更好。这也算是我在这个组件上最大的收获。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

Apache Pulsar Functions 状态存储机制:基于 BookKeeper Table Service 的 State API 全解析
Apache Pulsar Functions 状态存储机制:基于 BookKeeper Table Service 的 State API 全解析

消息队列后端流处理 【免费下载链接】pulsar Apache Pulsar - distributed pub-sub messaging system 项目地址: https://gitcode.com/gh_mirrors/pulsar28/pulsar 点击查看 免费下载 本篇技术指南围绕 Apache Pulsar 2.3.0 版本的官方文档 Pulsar Functions State… · 2026/9/25 2:18:24

NodeGui 中 QFontStretch 枚举详解:QFont 字体伸展度的 10 级取值与 NAPI 绑定实现
NodeGui 中 QFontStretch 枚举详解:QFont 字体伸展度的 10 级取值与 NAPI 绑定实现

桌面应用跨平台 【免费下载链接】nodegui A library for building cross-platform native desktop applications with Node.js and CSS 🚀. React NodeGui : https://react.nodegui.org and Vue NodeGui: https://vue.nodegui.org 项目地址: https://git… · 2026/9/25 2:18:18

吸烟数据集带标注:YOLOv8训练与小目标召回提升实战
吸烟数据集带标注:YOLOv8训练与小目标召回提升实战

简介:这份「吸烟数据集带标注」面向人工智能与机器学习方向的开发者、算法工程师及高校学生,用于训练和评估吸烟行为识别与预测模型。数据集以监督学习为目标,每个样本均带有吸烟者或非吸烟者的标注信息,可支撑分类、特征分析等典… · 2026/9/25 2:18:18

JUnit 4.9 发布要点深度解析:ClassRule 与 TestRule 如何把测试规则提升到类级别
JUnit 4.9 发布要点深度解析:ClassRule 与 TestRule 如何把测试规则提升到类级别

测试开发工具 【免费下载链接】junit4 A programmer-oriented testing framework for Java — :warning: maintenance mode 项目地址: https://gitcode.com/gh_mirrors/ju/junit4 点击查看 免费下载 本文基于 doc/ReleaseNotes4.9.md 中 JUnit 4.9 的官方发布说明展… · 2026/9/25 2:51:58

Multistage高回退Doherty功放的ADS理想电流源仿真与合成网络设计
Multistage高回退Doherty功放的ADS理想电流源仿真与合成网络设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:51:58

PHP The Right Way 系列:在 Ubuntu / Debian 上安装最新版 PHP——PPA 与 sury.org bikeshed 完整实战指南
PHP The Right Way 系列:在 Ubuntu / Debian 上安装最新版 PHP——PPA 与 sury.org bikeshed 完整实战指南

文档教程 【免费下载链接】php-the-right-way An easy-to-read, quick reference for PHP best practices, accepted coding standards, and links to authoritative tutorials around the Web 项目地址: https://gitcode.com/gh_mirrors/ph/php-the-right-way 点击… · 2026/9/25 2:51:52

C语言面试题深度总结:从关键字到内存管理的核心考点
C语言面试题深度总结:从关键字到内存管理的核心考点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:51:52

老 Mac 免费装新 macOS:OpenCore Legacy Patcher 三步实操指南
老 Mac 免费装新 macOS:OpenCore Legacy Patcher 三步实操指南

老 Mac 免费装新 macOS:OpenCore Legacy Patcher 三步实操指南 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 家里那台用了十年的 MacBook Pro&a… · 2026/9/25 2:51:52

Jupyter docker-stacks 开发环境搭建:本地复刻 CI 的检查、构建与测试流程
Jupyter docker-stacks 开发环境搭建:本地复刻 CI 的检查、构建与测试流程

云原生开发工具数据科学 【免费下载链接】docker-stacks Ready-to-run Docker images containing Jupyter applications 项目地址: https://gitcode.com/gh_mirrors/do/docker-stacks 点击查看 免费下载 本文基于仓库中的 开发环境指南 展开,系统讲解如… · 2026/9/25 2:51:52

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码