【问题标题】:PostgreSQL adds trailing zeros to numericPostgreSQL 将尾随零添加到数字
【发布时间】:2014-11-13 23:06:56
【问题描述】:

最近我将一个 DB 迁移到 PostgreSQL,其中一些列定义为 numeric(9,3)numeric(9,4)。在测试应用程序时,我发现当数据保存到这些列时,插入的值中会添加尾随零。我正在使用 Hibernate,我的日志显示为准备好的语句构建的正确值。

我插入的数据示例是 0.75numeric(9,3) 列中,存储的值是 0.750numeric(9,4) 列的另一个示例:我插入值 12 并且数据库持有 12.0000

我发现了这个相关问题:postgresql numeric type without trailing zeros。但除了引用 9.x 文档说不添加尾随零之外,它没有提供解决方案。从那个问题,答案引用了文档(我也读过)说:

数值是物理存储的,没有任何额外的前导或 尾随零。因此,列的声明精度和比例 是最大值,而不是固定分配。

但是,就像那个问题海报一样,我看到添加了尾随零。 Hibernate 在日志中生成的原始插入没有显示这个额外的包袱。所以我假设这是一个我没有正确设置的 PostgreSQL 东西,我只是找不到我是怎么弄错的。

【问题讨论】:

  • 您看到零的客户端是什么?你试过 psql 吗?
  • 这是一个网络应用程序,我使用 Firefox 作为我的浏览器。应用服务器是使用 Hibernate 的 Java。带有尾随零的“修改”值在实际数据库记录中可见(并在查询时以这种方式返回给客户端)。
  • 在实际数据库记录中可见是什么意思?客户向您展示了什么?我已经问过了,你没有回答:你试过 psql 了吗?
  • 是的,我确实尝试了一个 psql 查询,结果相同。由于我支持的应用程序使用 Java 和 Hibernate,所以这是我需要的组合。通过“在实际数据库记录中可见”,我指的是使用工具(在我的情况下为 pgAdmin3)查看时表中的内容。当您想要查看/编辑数据时,pgAdmin3 显示尾随零作为它执行的查询的结果......这就是 Web 浏览器显示来自服务器的内容。

标签: postgresql padding numeric


【解决方案1】:

如果我在这种情况下正确理解“强制”,我想就是这样。这是来自 PostgreSQL 文档:

数值列的最大精度和最大小数位数 可以配置。要声明数字类型的列,请使用以下语法:

NUMERIC(precision, scale)

精度必须为正数,刻度为零或正数。 或者:

NUMERIC(precision)

选择0的比例。指定:

NUMERIC

在没有任何精度或比例的情况下创建一列 可以存储任何精度和比例的数值,最多 精度的实施限制。这种列不会 将输入值强制为任何特定比例,而数字 具有声明比例的列将强制输入值到该比例。

我的大胆强调。

所以它在同一部分后面误导

数值以物理方式存储,没有任何额外的前导或 尾随零。因此,列的声明精度和小数位数 是最大值,而不是固定分配

再次大胆强调我的。

这可能适用于精度部分,但由于在定义比例时会强制转换比例,因此会将尾随零添加到输入值以满足比例定义(如果太大,我会假设被截断)。

我正在使用 precision,scale 定义来执行约束。正是在 DB 插入期间,将尾随零添加到数字刻度中,这似乎支持强制转换,并且与不添加尾随零的语句相冲突。

正确与否,我必须在选择完成后在代码中处理问题。对我来说幸运的是,受影响的属性是BigDecimal,因此去除尾随零很容易(尽管不优雅)。如果有人有更好的建议不要让 PostgreSQL 在插入时在数字刻度上添加尾随零,我愿意接受。

【讨论】:

    【解决方案2】:

    如果您指定精度和比例,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)                                                                                                                                                                        
    

    【讨论】:

    • PostgreSQL 的新手,所以如果我在数据库中定义为 numeric(9,4) 的列(如此处的 num_col )并且我执行普通 SQL 插入(插入 blah (pk, num_col ) values (1, 12);)...我的 12 现在是 12.0000,当我使用 SQL 或 psql 或 pgAdmin3 和 select...(select num_col from blah;) 来查看它时?比例和精度是在列本身上定义的(作为我的限制),而不是在我在选择期间使用的 SQL 中。在插入过程中,刻度由尾随零填充,直到定义的限制。对我来说,插入 12 应该存储 12(不是 12.0000)并且 SQL 选择应该得到相同的值?
    【解决方案3】:

    从 PostgreSQL v13 开始,您可以使用 trim_scale 函数去除训练零。这将减少数字的存储大小。

    【讨论】:

      猜你喜欢
      • 2018-03-14
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多