Rails:将列从十进制迁移到整数后,数据会发生什么

Mel*_*emi 2 migration postgresql ruby-on-rails

我总是冒险破坏我的开发数据库(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
Run Code Online (Sandbox Code Playgroud)

mu *_*ort 7

ActiveRecord将向数据库发送ALTER TABLE ALTER COLUMN ... TYPE,数据库将执行类型转换.PostgreSQL将转换decimalint使用round:

=> 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)
Run Code Online (Sandbox Code Playgroud)

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

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

optional USING子句指定如何从旧值计算新列值; 如果省略,则默认转换与从旧数据类型转换为new的赋值相同.一个USING如果从旧到新类型没有隐含或者赋值转换必须提供条款.

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

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