存储货币值:Numeric与Real类型对比及股票数据Schema选型疑问
作为SQL新手,你纠结这个问题太正常了——毕竟股票数据里的每一个小数位都可能关联真金白银,容不得半点儿误差。咱们从股票数据的特性和PostgreSQL两种类型的本质差异说起,你就能明白为什么这个建议必须遵守:
彻底避免浮点精度丢失问题
浮点类型(比如float、real)是用近似方式存储数值的,举个最简单的例子:你以为存进去的是0.1,但实际上数据库里存的是一个接近0.1的二进制近似值。股票价格通常精确到四位小数(比如你的Schema里定义的decimal 18,4),如果用浮点类型存储,多次计算(比如计算均价、累计收益、回测交易策略)后,这些微小的误差会被不断放大,最后得出完全偏离真实值的结果。而numeric类型是精确存储每一位数字的,完全能匹配股票价格的精度要求,不会出现这类“隐形误差”。满足金融数据的准确性与合规要求
股票数据属于典型的金融类数据,不管是日常的交易记录、清算对账,还是回测投资策略,都需要绝对精确的数值。差0.0001元看起来不多,但如果涉及大量交易或者长期数据累积,误差可能会导致错误的决策,甚至违反金融数据的合规记录要求。用numeric类型能保证每一个价格数值和原始数据完全一致,从根源上杜绝这类问题。贴合你的Schema设计初衷
你给出的股票数据Schema里,Open、High、Low、Close字段都定义为decimal 18,4——而在PostgreSQL中,decimal和numeric是完全等价的同义词。遵循文档建议用numeric,其实就是严格贴合你一开始的Schema设计,确保数据存储和计算的一致性,不会出现“定义是decimal但实际用了float”的矛盾。
PostgreSQL官方文档也明确指出:
若需精确存储与计算(如货币金额),应使用numeric类型替代浮点类型
最后提个小细节:你的Schema里Volume用int是完全没问题的,因为成交量本身就是整数;但所有价格类字段,一定要坚持用numeric(也就是你定义的decimal),别图一时方便用浮点类型,不然后期排查精度问题会让你头疼不已。
内容的提问来源于stack exchange,提问作者Steve Kennedy




