Delphi 开发避坑终极指南:数据库 Decimal (18,6) 类型选择,别再用错 Double 和 Currency!

一、前言

做 Delphi 业务系统、ERP、金融、交易、支付相关开发时,一定会遇到:

数据库字段:decimal(18,6) 问题:Delphi 端应该用什么类型接收?

网上常见错误答案:

  • 用 Double(精度隐患)
  • 用 Currency(直接丢数据)
  • 很少有人提到真正标准的 TBcd

本文结合实战 + 精度原理,给出最正确、最安全、工业级方案。


二、先明确:decimal (18,6) 是什么?

  • 总长度:18 位数字
  • 小数固定:6 位
  • 要求:绝对精确、不能四舍五入、不能丢位
  • 典型场景:金额、费率、汇率、重量、交易金额、第三方接口数据

这种数据绝对不能用不精确类型


三、致命错误:千万不要用 Currency

很多人被名字误导:

"Currency 是货币类型,存金额最安全!"

大错特错!

Currency 真相

  • 固定 4 位小数
  • 底层:Int64 / 10000
  • 存入 6 位小数 → 强制四舍五入到第 4 位

示例

plaintext

复制代码
数据库:123.456789
Currency 存储:123.4568

后两位小数直接丢失,永久无法恢复!

这不是精度问题,是数据损坏

结论decimal(18,6) 场景 严禁使用 Currency


四、勉强能用:Double 比 Currency 好,但不推荐

客观事实:Double 确实比 Currency 好很多

原因:

  • Double 能保存 15~16 位有效数字
  • 不会截断 6 位小数
  • 但它是二进制浮点数,天生精度误差

例如:

plaintext

复制代码
0.1 + 0.2 = 0.3000000000000001

结论

  • 临时、非核心数据可以用
  • 金融、金额、交易、高精度业务 严禁使用

五、正确方案 1:Int64(交易 / 支付 工业标准)

这是你提到的最小单位法,也是微信支付、支付宝、银联、交易接口通用标准:

把数值 ×1000000 用整数存储

示例:

plaintext

复制代码
123.456789 → 存储为 123456789(Int64)

优点

  • ✅ 100% 精确,无任何精度丢失
  • ✅ 完美匹配 6 位小数
  • ✅ 整数运算极快
  • ✅ 跨语言、跨系统无歧义

Delphi 代码模板

delphi

复制代码
const
  SCALE = 1000000; // 6 位小数放大倍数
var
  Price: Int64;
begin
  // 从数据库读取
  Price := Round(DataSet['price'].AsFloat * SCALE);

  // 计算(全整数,绝对精确)
  Price := Price + 100000; // +0.100000

  // 显示
  Caption := FormatFloat('0.000000', Price / SCALE);
end;

六、正确方案 2:TBcd(Delphi 官方正统首选)

重点来了!Delphi 原生专门对应数据库 decimal 的精确类型:TBcd

单元:

delphi

复制代码
Data.FmtBcd

TBcd 是什么?

  • 数据库 decimal/numeric原生内存结构
  • 100% 精确十进制
  • 支持任意精度(完美支持 18,6)
  • 无浮点误差
  • TBCDField 底层就是 TBcd

实战代码

delphi

复制代码
uses Data.FmtBcd;

var
  A, B, C: TBcd;
begin
  // 赋值
  A := StrToBcd('123.456789');
  B := StrToBcd('456.987654');

  // 精确运算
  C := BcdAdd(A, B);  // 加
  C := BcdSub(A, B);  // 减
  C := BcdMul(A, B);  // 乘
  C := BcdDiv(A, B);  // 除

  // 显示
  Caption := BcdToStr(C);
end;

数据库直接读取(零损耗、最标准)

delphi

复制代码
var
  Value: TBcd;
begin
  Value := DataSet['price'].AsBcd;
end;

七、TBcd vs Int64 怎么选?

两个都是 100% 精确 正确方案!

选 TBcd

  • 标准业务系统、ERP、管理系统
  • 大量数据库操作
  • 希望代码最规范、最简单
  • 不想手动缩放(×1000000)

选 Int64

  • 支付、交易、对接第三方接口
  • 跨语言、跨平台
  • 追求极致性能
  • 习惯最小单位设计

八、终极推荐排名(永不踩坑)

针对 decimal(18,6)

  1. 🥇 TBcd(Data.FmtBcd) 官方标准、100% 精确、完美匹配→ 业务系统首选

  2. 🥈 Int64 交易 / 支付标准、极快、精确→ 接口 / 交易系统首选

  3. 🥉 Double有精度风险,仅临时凑合→ 不推荐用于核心数据

  4. ❌ Currency 固定 4 位小数,直接丢失 2 位数据→ 绝对禁用


九、总结(金句)

  1. Delphi 处理 decimal(18,6)只有 TBcd 和 Int64 是正确方案
  2. Currency 固定 4 位小数,会直接损坏 6 位数据
  3. Double 有精度隐患,只能算备胎
  4. 业务系统用 TBcd,交易接口用 Int64
  5. 固定小数位 = 精确类型 = 行业标准,绝不妥协!

十、结束语

精度问题在金融、交易、金额类系统中是红线问题。希望这篇文章能帮你避开 Delphi 中最常见的数值类型坑。

如果你也在做高精度计算、金额计算、对接支付接口,欢迎点赞、收藏、关注!

相关推荐
计算机安禾3 小时前
【数据库系统原理】第19篇:计算机存储层次结构与数据库文件的物理组织
数据库·oracle
JAVA面经实录9173 小时前
操作系统面试题
java·服务器·数据库·计算机网络·面试
摇滚侠3 小时前
mariadb-libs 被 mysql-community-libs-5.7.28-1.el7.x86_64 取代
数据库·mysql·mariadb
DIY源码阁4 小时前
JavaSwing饮品管理系统 - MySQL版
java·数据库·mysql·eclipse
专注搞钱4 小时前
GPT-4o写设备Recipe:从3小时到10分钟
数据库·人工智能·gpt·半导体
东风破1375 小时前
达梦数据库实战:备份恢复与数据迁移全攻略(实例初始化、服务注册、路径迁移)
数据库·chrome
SelectDB技术团队5 小时前
2026 SelectDB AI 产品发布会:Agent Native 数据基础设施能力全景发布
数据库·人工智能·agent·apache doris·selectdb
爱吃羊的老虎5 小时前
【数据库】模块一:数据库基础与关系代数
数据库
dishugj6 小时前
iSCSI + Multipath + ASM:Oracle RAC 共享存储技术链详解
数据库·oracle
yoothey6 小时前
MySQL事务机制解析 - 面试高分知识点
数据库·mysql·面试