代码之家  ›  专栏  ›  技术社区  ›  LakeHMM

如何在使用Rails的PostgreSQL中将时间列更改为整数列?

  •  5
  • LakeHMM  · 技术社区  · 7 年前

    我有一个名为 duration 在名为 time_entries 在连接到新Rails应用程序的PostgreSQL数据库中。它当前的格式是时间数据,但我希望它是一个整数。(具体来说,我将使用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 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代码一无所知。非常感谢。

    3 回复  |  直到 7 年前
        1
  •  3
  •   Nick    7 年前

    您可以很容易地从时间值中提取历元(秒数):

    SELECT EXTRACT(EPOCH FROM '01:00:00'::TIME)::INT
    -- Returns 3600 
    

    在你的情况下,我怀疑你可以这样做:

    change_column :time_entries, :duration, 'integer USING EXTRACT(EPOCH FROM duration)::INT'
    
        2
  •  2
  •   Erwin Brandstetter    7 年前

    您需要提供一个表达式来使用 USING 条款:

    ALTER TABLE time_entries ALTER duration TYPE int2 USING EXTRACT(EPOCH FROM duration)::int2;
    

    请注意,任何超过 smallint 将引发异常,中止整个事务。

    D小提琴 here

    相关:

        3
  •  1
  •   LakeHMM    7 年前

    由于其他答案中提供的信息,我在Rails迁移中完成了以下工作:

    change_column :time_entries, :duration, 'SMALLINT USING EXTRACT(EPOCH FROM duration)/60::SMALLINT'
    

    这将列转换为表示分钟数的SMALLINT数字。我只是想在这里包含最终的解决方案,因为我对其他答案的代码做了一些修改。