【问题标题】:Why is postgreSQL storing a decimal field as a BigDecimal hash?为什么 postgreSQL 将十进制字段存储为 BigDecimal 哈希?
【发布时间】:2012-02-28 22:09:48
【问题描述】:

我在 rails3/postgreSQL 中有以下模型/表:

create_table "admin_reports", :force => true do |t|
  t.string   "report"
  t.decimal  "result"
  t.string   "result_type"
  t.datetime "created_at"
  t.datetime "updated_at"
end

在生产中,AdminReports.result 不存储小数,而是存储哈希:

AdminReport.last

=> #<AdminReport id: 4, report: "dau", result: #<BigDecimal:cbca0f0,'0.8E1',4(8)>, result_type: "percentage", created_at: "2012-02-28 22:05:15", updated_at: "2012-02-28 22:05:15">

我希望看到的地方:

AdminReport.last

=> #<AdminReport id: 4, report: "dau", result: 10.10, result_type: "percentage", created_at: "2012-02-28 22:05:15", updated_at: "2012-02-28 22:05:15">

在 Rails 控制台中,即使我尝试像这样手动设置结果字段:

@a = AdminReport.last
@a.result = 8.89
@a.save

它仍然将 AdminReport.result 显示为 BigDecimal 哈希。有什么想法吗?

谢谢

【问题讨论】:

  • 这就是你调用 .inspect 时输出的大十进制数(控制台就是这样做的)。
  • 所以我不应该使用十进制作为字段吗?我应该使用什么字段,以便它实际输出值(10.10)?奇怪的是,它并没有在本地这样做。

标签: ruby-on-rails ruby-on-rails-3 postgresql


【解决方案1】:

您使用的是小数列:

create_table "admin_reports", :force => true do |t|
  #...
  t.decimal  "result"
  #...
end

这通常意味着您想使用固定的小数位数,因此您可能还想指定:precision 和:scale 选项。当 ActiveRecord 看到小数列时,它会将值转换为 Ruby 的 BigDecimal,以便您可以在 Ruby-land 中保持所需的小数位数;如果 AR 使用浮点值,那么您会遇到所有常见的浮点问题,您最终可能会从数据库中提取一个值并将另一个值放回 而不是故意更改它,使用BigDecimal 完全避免了这个问题。

当你看到这个时:

#<BigDecimal:cbca0f0,'0.8E1',4(8)>

您只是看到 BigDecimal 的标准 inspect 输出。如果您使用to_s(或"#{...}"),您会看到更熟悉的内容。

所以没有什么可担心的。如果您需要使用非整数运算但又不想遇到所有浮点问题,那么十进制列(带有:precision 和:scale)是正确的选择。

【讨论】:

  • 谢谢,我该如何使用支持 2 位小数 w 精度和 :scale 的字段?
  • @AnApprentice:你需要:scale =&gt; 2。或许也可以看看 PostgreSQL 文档:postgresql.org/docs/current/interactive/…
  • 只是要指出,在较新的 Rails 版本中,您仍然会看到 BigDecimal 符号中的数字,只是没有完整的哈希,只需要使用 .to_s 方法,一切都会好起来的。跨度>
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 2013-10-06
  • 1970-01-01
  • 2015-11-03
  • 2014-07-24
  • 2018-03-30
  • 2013-11-11
  • 2020-07-27
相关资源
最近更新 更多