如何将 Rails 数据类型更改为 PostGres bigint?
How do I change my Rails datatype to PostGres bigint?
我正在尝试 运行 以下 Rails 迁移,使用 Rails 4.2.4 和 PostGresql …
class ChangeTimeInMsColInMyObjectTimes < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :integer, :limit => 8
end
end
但它会导致以下错误。我
rake db:migrate
== 20160613195631 ChangeTimeInMsColInMyObjectTimes: migrating =====================
-- change_column(:my_object_times, :time_in_ms, :integer, {:limit=>8})
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 bigint
HINT: You might need to specify "USING time_in_ms::bigint".
: ALTER TABLE "my_object_times" ALTER COLUMN "time_in_ms" TYPE bigint
/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'
我需要在迁移中使用的正确语法是什么?
谢谢,-戴夫
如错误消息所述,您无法自动将 interval
转换为 bigint
。你也不能简单地转换它,所以建议的 using time_in_ms::bigint
也不起作用。
虽然这个建议部分正确,但在更改列的类型时手动整理类型转换的常用方法是在 ALTER TABLE 中使用 USING 子句,因此您需要做的就是找出哪个用于将 interval
转换为毫秒数的表达式 bigint
.
在数据库中对时间类型进行切片和切块的常用方法是使用 extract
:
9.9.1. EXTRACT, date_part
EXTRACT(field FROM source)
The extract
function retrieves subfields such as year or hour from date/time values. [...] The extract function returns values of type double precision
.
在这种情况下,字段 是您感兴趣的时间部分,epoch
可能是您所追求的:
epoch
[...] for interval values, the total number of seconds in the interval
extract
以双精度形式给出秒数,因此您必须自己将秒数转换为毫秒数。类似于:
using extract(epoch from time_in_ms) * 1000
应该可以解决问题。在迁移中,这将是:
change_column :my_object_times, :time_in_ms, :integer, :limit => 8, :using => 'extract(epoch from time_in_ms) * 1000'
或
change_column :my_object_times, :time_in_ms, :bigint, :using => 'extract(epoch from time_in_ms) * 1000'
我正在尝试 运行 以下 Rails 迁移,使用 Rails 4.2.4 和 PostGresql …
class ChangeTimeInMsColInMyObjectTimes < ActiveRecord::Migration
def change
change_column :my_object_times, :time_in_ms, :integer, :limit => 8
end
end
但它会导致以下错误。我
rake db:migrate
== 20160613195631 ChangeTimeInMsColInMyObjectTimes: migrating =====================
-- change_column(:my_object_times, :time_in_ms, :integer, {:limit=>8})
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 bigint
HINT: You might need to specify "USING time_in_ms::bigint".
: ALTER TABLE "my_object_times" ALTER COLUMN "time_in_ms" TYPE bigint
/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'
我需要在迁移中使用的正确语法是什么?
谢谢,-戴夫
如错误消息所述,您无法自动将 interval
转换为 bigint
。你也不能简单地转换它,所以建议的 using time_in_ms::bigint
也不起作用。
虽然这个建议部分正确,但在更改列的类型时手动整理类型转换的常用方法是在 ALTER TABLE 中使用 USING 子句,因此您需要做的就是找出哪个用于将 interval
转换为毫秒数的表达式 bigint
.
在数据库中对时间类型进行切片和切块的常用方法是使用 extract
:
9.9.1. EXTRACT, date_part
EXTRACT(field FROM source)
The
extract
function retrieves subfields such as year or hour from date/time values. [...] The extract function returns values of typedouble precision
.
在这种情况下,字段 是您感兴趣的时间部分,epoch
可能是您所追求的:
epoch
[...] for interval values, the total number of seconds in the interval
extract
以双精度形式给出秒数,因此您必须自己将秒数转换为毫秒数。类似于:
using extract(epoch from time_in_ms) * 1000
应该可以解决问题。在迁移中,这将是:
change_column :my_object_times, :time_in_ms, :integer, :limit => 8, :using => 'extract(epoch from time_in_ms) * 1000'
或
change_column :my_object_times, :time_in_ms, :bigint, :using => 'extract(epoch from time_in_ms) * 1000'