【问题标题】:Rails: what happens to data after migrating column from decimal to integerRails:将列从十进制迁移到整数后数据会发生什么
【发布时间】:2013-01-19 20:13:23
【问题描述】:

我总是冒着搞砸我的开发数据库 (PostgreSQL) 并重建它的风险,但我想我会先问问是否有人有经验。

理想情况下,所有数据都将被截断为整数:(例如:5.7 将变为 5)或者它可能会将值舍入(5.7 变为 6)?或者它只是简单地取消或清零所有值并且数据丢失?我想最坏的结果是不可靠的数据(5.7 变成 23)。

这些类型的迁移是否有一般的经验法则?

class ChangeBookFromDecimalToInteger < ActiveRecord::Migration
  def self.up
   change_column :book, :price, :integer
  end

  def self.down
   change_column :book, :price, :decimal
  end
end

【问题讨论】:

  • 这里附带的一点是,您很幸运地使用了一个数据库,其中除了创建/删除数据库和创建/删除表空间和序列以及它们的功能之外的一切都是可交易的。因此,请尝试您在开发数据库上的事务中正在查看的内容,看看会发生什么。如果您不是 100% 满意,请回滚。请注意,现在是学习如何从 psql 命令界面驱动数据库的好时机,它非常强大且用户友好。
  • 我可能会误解你...你是说从psql 命令行运行迁移可能比 Rails 迁移更有利吗?我认为这会很危险,因为团队中的其他用户无法轻松访问存储库中的相同迁移。或者你只是说使用命令行来“玩”迁移,直到找到你需要的东西,因为它们很容易回滚?!?
  • 你真的可以做一个或两个。但绝对要测试会发生什么等。例如,正如其他地方提到的,活动记录不理解 using 子句,因此如果您需要一个,您将手动迁移数据。

标签: ruby-on-rails postgresql migration


【解决方案1】:

ActiveRecord 将发送一个 ALTER TABLE ALTER COLUMN ... TYPE 到数据库,数据库将执行类型转换。 PostgreSQL 将使用rounddecimal 转换为int

=> create table with_decimal (n decimal(11, 6));
=> insert into with_decimal (n) values (1.0),(1.1),(1.5),(1.6),(1.9);
=> insert into with_decimal (n) values (-1.0),(-1.1),(-1.5),(-1.6),(-1.9);
=> select * from with_decimal;
     n     
-----------
  1.000000
  1.100000
  1.500000
  1.600000
  1.900000
 -1.000000
 -1.100000
 -1.500000
 -1.600000
 -1.900000
(10 rows)

=> alter table with_decimal alter column n type int;
=> select * from with_decimal;
 n  
----
  1
  1
  2
  2
  2
 -1
 -1
 -2
 -2
 -2
(10 rows)

请注意,round(numeric) 会舍入到最接近的整数。

如果您想要特定的转换行为,您应该在ALTER TABLE 中使用 USING 说明:

可选的USING 子句指定如何从旧列值计算新列值;如果省略,则默认转换与从旧数据类型到新数据类型的赋值转换相同。如果没有从旧类型到新类型的隐式或赋值强制转换,则必须提供 USING 子句。

如果您需要 USING 子句,则必须手动发出 ALTER TABLE,因为 ActiveRecord 对 USING 一无所知,例如:

def up
    connection.execute(%q{
        alter table books
        alter column price 
        type integer
        using trunc(price * 100)
    })
end

【讨论】:

    【解决方案2】:

    您需要查阅 PostreSQL 手册,了解它如何处理诸如“ALTER TABLE ... CHANGE COLUMN ...”之类的查询以及如何在相应类型之间转换数据。
    Rails 中的所有 DB Schema 更改迁移都由相应的数据库后端处理。

    【讨论】:

      【解决方案3】:

      一般的经验法则是,如果您必须迁移,并且需要明确的要求,请创建新列,使用 Ruby 转换列,然后删除旧列。如果你不关心数据,让数据库通过ALTER TABLE来处理

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-08
        相关资源
        最近更新 更多