如何使用 Rails 将 PostgreSQL 中的时间列更改为整数列?
How do I change a time column to an integer column in PostgreSQL with Rails?
我在连接到新 Rails 应用程序的 PostgreSQL 数据库中的 table 中有一个名为 duration
的列,名为 time_entries
。它目前被格式化为时间数据,但我希望它是一个整数。 (具体来说,我打算使用 smallint 专栏,因为它的分钟数不会超过一天,即 1440。)
首先,我试过:
change_column :time_entries, :duration, :smallint, limit: 2
但是我得到以下错误:
PG::DatatypeMismatch: ERROR: column "duration" cannot be cast automatically to type smallint
HINT: You might need to specify "USING duration::smallint".
然后,在查看 this post and this post 之后,我尝试了以下迁移:
change_column :time_entries, :duration, 'integer USING CAST(duration AS integer)'
change_column :time_entries, :duration, :smallint, limit: 2
但第一行返回以下错误:
PG::CannotCoerce: ERROR: cannot cast type time without time zone to integer
如何转换?时区无关紧要,因为它实际上表示持续时间。我是 Rails 新手,对原始 SQL 代码一无所知。谢谢!
您需要提供一个表达式来使用 USING
子句进行实际转换:
ALTER TABLE time_entries ALTER duration TYPE int2 USING EXTRACT(EPOCH FROM duration)::int2;
请注意,任何超出 smallint
范围的值都会引发异常,从而中止整个事务。
dbfiddle here
相关:
- Rails Migrations: tried to change the type of column from string to integer
- Get a timestamp from concatenating day and time columns
您可以很容易地从 TIME 值中提取纪元(秒数):
SELECT EXTRACT(EPOCH FROM '01:00:00'::TIME)::INT
-- Returns 3600
对于你的情况,我怀疑你可以这样做:
change_column :time_entries, :duration, 'integer USING EXTRACT(EPOCH FROM duration)::INT'
感谢其他答案中提供的信息,我在 Rails 迁移中执行了以下操作:
change_column :time_entries, :duration, 'SMALLINT USING EXTRACT(EPOCH FROM duration)/60::SMALLINT'
这将列转换为代表分钟数的 SMALLINT 数字。我只是想在这里包含最终解决方案,因为我稍微修改了其他答案的代码。
我在连接到新 Rails 应用程序的 PostgreSQL 数据库中的 table 中有一个名为 duration
的列,名为 time_entries
。它目前被格式化为时间数据,但我希望它是一个整数。 (具体来说,我打算使用 smallint 专栏,因为它的分钟数不会超过一天,即 1440。)
首先,我试过:
change_column :time_entries, :duration, :smallint, limit: 2
但是我得到以下错误:
PG::DatatypeMismatch: ERROR: column "duration" cannot be cast automatically to type smallint
HINT: You might need to specify "USING duration::smallint".
然后,在查看 this post and this post 之后,我尝试了以下迁移:
change_column :time_entries, :duration, 'integer USING CAST(duration AS integer)'
change_column :time_entries, :duration, :smallint, limit: 2
但第一行返回以下错误:
PG::CannotCoerce: ERROR: cannot cast type time without time zone to integer
如何转换?时区无关紧要,因为它实际上表示持续时间。我是 Rails 新手,对原始 SQL 代码一无所知。谢谢!
您需要提供一个表达式来使用 USING
子句进行实际转换:
ALTER TABLE time_entries ALTER duration TYPE int2 USING EXTRACT(EPOCH FROM duration)::int2;
请注意,任何超出 smallint
范围的值都会引发异常,从而中止整个事务。
dbfiddle here
相关:
- Rails Migrations: tried to change the type of column from string to integer
- Get a timestamp from concatenating day and time columns
您可以很容易地从 TIME 值中提取纪元(秒数):
SELECT EXTRACT(EPOCH FROM '01:00:00'::TIME)::INT
-- Returns 3600
对于你的情况,我怀疑你可以这样做:
change_column :time_entries, :duration, 'integer USING EXTRACT(EPOCH FROM duration)::INT'
感谢其他答案中提供的信息,我在 Rails 迁移中执行了以下操作:
change_column :time_entries, :duration, 'SMALLINT USING EXTRACT(EPOCH FROM duration)/60::SMALLINT'
这将列转换为代表分钟数的 SMALLINT 数字。我只是想在这里包含最终解决方案,因为我稍微修改了其他答案的代码。