【问题标题】:PG::Error timezone when changing string column to time data type将字符串列更改为时间数据类型时的 PG::Error timezone
【发布时间】:2018-12-28 22:10:15
【问题描述】:

我需要更改列数据类型,目前这些列是字符串,但我需要更改为“时间”。

迁移文件:

def change
  change_column :enquiries, :start_time, :time
  change_column :enquiries, :end_time, :time
end

错误信息:

PG::Error: ERROR: column "start_time" 不能自动转换为 键入不带时区的时间 提示:您可能需要指定“使用 start_time::time without time zone"。

经过一些搜索,我找到了这个解决方案,但它仍然无法正常工作,但是我收到了新的错误消息。

def change
  change_column :enquiries, :start_time, 'time USING CAST(start_time AS time)'
  change_column :enquiries, :end_time, 'time USING CAST(end_time AS time)'
end

PG::Error: ERROR: 类型时间的无效输入语法:“”

我尝试了 ma​​tthewd 解决方案,但仍然无法正常工作。

change_column :enquiries, :start_time, "time USING CAST(NULLIF(start_time, '') AS time)"

PG::Error: ERROR: 类型时间无效的输入语法:“09.00”

任何帮助如何解决它?

【问题讨论】:

    标签: ruby-on-rails string postgresql rails-migrations


    【解决方案1】:

    基本上,这就是我所做的。有很多 start_time 和 end_time 记录,这两列没有验证,所以有些记录的格式不正确(HH:MM)。 但是,需要重构此代码,但这对我有用。

    def up
      rename_column :enquiries, :start_time, :start_time_old
      rename_column :enquiries, :end_time, :end_time_old
      add_column :enquiries, :start_time, :time
      add_column :enquiries, :end_time, :time
    
      Enquiry.reset_column_information
      Enquiry.find_each do |e| 
        unless e.start_time_old.blank?
          if e.start_time_old.include?('.')
            e.update_column(:start_time , e.start_time_old.gsub('.', ':'))
          else
            e.update_column(:start_time , e.start_time_old)
          end
        end
      end
    
      Enquiry.find_each do |e| 
        unless e.end_time_old.blank?
          if e.end_time_old.include?('.')
            e.update_column(:end_time , e.end_time_old.gsub('.', ':'))
          else
            e.update_column(:end_time , e.end_time_old)
          end
        end
      end
    
      remove_column :enquiries, :start_time_old
      remove_column :enquiries, :end_time_old
    end
    

    【讨论】:

      【解决方案2】:

      第二个错误是由在您的 *_time 列之一中具有空白字符串作为其值的现有行引起的:正如它所说,这不是 time 类型的有效输入。

      最合理的选择是将它们转换为 NULL,您可以使用NULLIF SQL 函数来做到这一点:

      change_column :enquiries, :start_time, "time USING CAST(NULLIF(start_time, '') AS time)"
      

      【讨论】:

      • 如果start_timeend_time 列中有更多垃圾,则在列更改之前将up/down 方法与execute('update ...') 分开。您可以在演员表表达式中加入更多内容,但根据垃圾的性质,它可能会变得丑陋。
      • 用户也可以这样做:change_column :enquiries, :start_time, :time, using: "CAST(NULLIF(start_time, '') AS time)" 将列类型保留为 arg。
      猜你喜欢
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 2019-08-14
      • 2014-04-09
      • 2022-06-11
      • 2021-01-07
      • 1970-01-01
      相关资源
      最近更新 更多