最近我将数据库迁移到PostgreSQL,其中有一些列定义为numeric(9,3)
和numeric(9,4)
。在测试应用程序时,我发现当数据保存到这些列时,会在插入的值中添加尾随零。我正在使用Hibernate,我的日志显示为准备好的语句构建的正确值。
我插入的数据示例是numeric(9,3)
列中的 0.75 ,存储的值是 0.750 。 numeric(9,4)
列的另一个示例:我插入值 12 ,数据库持有 12.0000 。
我发现了这个相关的问题:postgresql numeric type without trailing zeros。但它没有提供解决方案,除了引用9.x文档说没有添加尾随零。从这个问题来看,答案引用了文件(我也读过),其中说:
数字值是物理存储的,没有任何额外的前导或 尾随零。因此,声明了列的精度和比例 是最大值,而不是固定分配。
然而,就像那个问题海报一样,我看到添加了尾随零。 Hibernate在日志中生成的原始插入不会显示这个额外的行李。所以我假设它是一个我没有正确设置的PostgreSQL,我只是找不到我是怎么做错的。
答案 0 :(得分:6)
如果指定精度和比例,Pg将达到该精度和比例。
regress=> SELECT '0'::NUMERIC(8,4);
numeric
---------
0.0000
(1 row)
没有办法把它关掉。它仍然是相同的数字,精度由类型而不是值定义。
如果您想要使用值定义的精度,则必须使用无约束numeric
:
regress=> SELECT '0'::NUMERIC, '0.0'::NUMERIC;
numeric | numeric
---------+---------
0 | 0.0
(1 row)
答案 1 :(得分:5)
我认为就是这样,如果我理解"强迫"正确地在这种情况下。这来自PostgreSQL文档:
数字列的最大精度和最大比例 可以配置。要声明numeric类型的列,请使用以下语法:
NUMERIC(precision, scale)
精度必须为正,刻度为零或正。 可替换地:
NUMERIC(precision)
选择0的比例。指定:
NUMERIC
没有任何精度或比例创建一个列 可以存储任何精度和比例的数值,最多可以存储 精度的实施限制。这类专栏不会 将输入值强制转换为任何特定比例, 而数字 具有声明比例的列将强制输入值到该比例。
大胆强调我的。
以后在同一部分中 误导 :
数字值在物理上 存储,没有任何额外的前导或 尾随零。因此,声明了列的精度和比例 是最大值,而不是固定分配 。
再次强调我的重点。
对于精度部分可能也是如此,但由于在定义时强制缩放比例,因此将尾随零添加到输入值以满足比例定义(如果太大,我会假设被截断)。 / p>
我正在使用 precision,scale 定义来执行约束。在数据库插入期间,尾随零被添加到数字刻度,这似乎支持强制并且与添加无尾随零的语句冲突。
是否正确,我必须在选择完成后处理代码中的问题。幸运的是,受影响的属性是BigDecimal
,因此剥离尾随零很容易(尽管不是很优雅)。如果那里有人有更好的建议没有PostgreSQL在插入数字刻度上添加尾随零,我向他们开放。
答案 2 :(得分:1)
从 PostgreSQL v13 开始,您可以使用 trim_scale
函数去除训练零。这将减少号码的存储大小。