如何在 Rails 迁移中将列类型更改为间隔?
How do I change my column type to interval in my Rails migration?
我正在使用 Rails 4.2.3 和 PostGre 数据库。我正在尝试将 table 中的列类型更改为“间隔”类型,因此我尝试了此迁移
class ChangeTimeInMsInMyObjectTimes < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :interval
end
end
但是在运行“rake db:migrate”时,我得到了下面令人失望的错误……
== 20160530164019 ChangeTimeInMsInMyObjectTimes: migrating ========================
-- change_column(:my_object_times, :time_in_ms, :interval)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::DatatypeMismatch: ERROR: column "time_in_ms" cannot be cast automatically to type interval
HINT: You might need to specify "USING time_in_ms::interval".
: ALTER TABLE "my_object_times" ALTER COLUMN "time_in_ms" TYPE interval
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activesupport-4.2.5.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
如何更改我的迁移以使其正常工作?
问题是 Postgres 不知道如何将整数(我假设 time_in_ms
现在就是这样。)转换为一个区间。但是您可以使用 USING
关键字告诉它如何操作。它采用 Postgres 将用来转换所有旧值的表达式。因此,您可以在迁移中使用它:
change_column :my_object_times, :time_in_ms,
"interval USING (time_in_ms || ' milliseconds')::interval"
请注意,如果您这样做,您应该编写单独的 up
和 down
方法,因为这种使用 change_column
的方式不会自动逆转。
哦还有:你可以忽略@Boltz0r 的要点。正如@mu 所说,它正试图解决一个不同的问题。
尝试
class ChangeTimeInMsInMyObjectTimes < ActiveRecord::Migration
def change
remove_column :my_object_times, :time_in_ms, :your_current_type
add_column :my_object_times, :time_in_ms, :interval
end
end
我正在使用 Rails 4.2.3 和 PostGre 数据库。我正在尝试将 table 中的列类型更改为“间隔”类型,因此我尝试了此迁移
class ChangeTimeInMsInMyObjectTimes < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :interval
end
end
但是在运行“rake db:migrate”时,我得到了下面令人失望的错误……
== 20160530164019 ChangeTimeInMsInMyObjectTimes: migrating ========================
-- change_column(:my_object_times, :time_in_ms, :interval)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::DatatypeMismatch: ERROR: column "time_in_ms" cannot be cast automatically to type interval
HINT: You might need to specify "USING time_in_ms::interval".
: ALTER TABLE "my_object_times" ALTER COLUMN "time_in_ms" TYPE interval
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `async_exec'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:155:in `block in execute'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activesupport-4.2.5.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/Users/davea/.rvm/gems/ruby-2.3.0@global/gems/activerecord-4.2.5.1/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
如何更改我的迁移以使其正常工作?
问题是 Postgres 不知道如何将整数(我假设 time_in_ms
现在就是这样。)转换为一个区间。但是您可以使用 USING
关键字告诉它如何操作。它采用 Postgres 将用来转换所有旧值的表达式。因此,您可以在迁移中使用它:
change_column :my_object_times, :time_in_ms,
"interval USING (time_in_ms || ' milliseconds')::interval"
请注意,如果您这样做,您应该编写单独的 up
和 down
方法,因为这种使用 change_column
的方式不会自动逆转。
哦还有:你可以忽略@Boltz0r 的要点。正如@mu 所说,它正试图解决一个不同的问题。
尝试
class ChangeTimeInMsInMyObjectTimes < ActiveRecord::Migration
def change
remove_column :my_object_times, :time_in_ms, :your_current_type
add_column :my_object_times, :time_in_ms, :interval
end
end