Mysql 在Rails迁移中如何将列从整数改为datetime?
我有一个名为record_time的列来存储记录的时间当前列数据类型为integer,数据保存为unix时间戳现在我想找到一种方法将此unix时间戳转换为datetime字段,而不会丢失该列中的数据。现在,我创建了一个迁移文件,如下所示:Mysql 在Rails迁移中如何将列从整数改为datetime?,mysql,ruby-on-rails,datetime,integer,migration,Mysql,Ruby On Rails,Datetime,Integer,Migration,我有一个名为record_time的列来存储记录的时间当前列数据类型为integer,数据保存为unix时间戳现在我想找到一种方法将此unix时间戳转换为datetime字段,而不会丢失该列中的数据。现在,我创建了一个迁移文件,如下所示: class ChangeRecordTimeToDatetime < ActiveRecord::Migration def up as = Audio.all.map {|a| {id: a.id, record_time: Time.at
class ChangeRecordTimeToDatetime < ActiveRecord::Migration
def up
as = Audio.all.map {|a| {id: a.id, record_time: Time.at(a.record_time)}}
Audio.all.update_all("record_time = NULL")
change_column :audios, :record_time, :datetime
as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])}
end
def down
as = Audio.all.map {|a| {id: a.id, record_time: a.record_time.to_i}}
Audio.all.update_all("record_time = NULL")
change_column :audios, :record_time, :integer
as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])}
end
end
提前感谢。在插入UNIX时间戳之前,需要将其转换为DateTime对象。您可以这样做:DateTime.strtime,'%s' 因此,要将此应用于您的问题,请尝试以下方法:
def up
as = Audio.all.map {|a| {id: a.id, record_time: DateTime.strptime(a.record_time.to_s, '%s')}}
remove_column :audios, :record_time
add_column :audios, :record_time, :datetime
as.map {|a| Audio.find(a[:id]).update(record_time: a[:record_time])}
end
对于这类事情,我会完全跳过ActiveRecord,并在数据库中完成。一些数据库允许在更改列的类型时指定如何将旧值转换为新值,但我不知道如何使用MySQL实现这一点;相反,您可以手动完成: 添加具有新数据类型的新列。 在转换日期类型时,执行一次更新,将旧值复制到新列。您可以使用MySQL来实现这一点。 删除原始列。 将新列重命名为旧名称。 重建原始列上的所有索引。 将其转化为迁移:
def up
connection.execute(%q{
alter table audios
add record_time_tmp datetime
})
connection.execute(%q{
update audios
set record_time_tmp = from_unixtime(record_time)
})
connection.execute(%q{
alter table audios
drop column record_time
})
connection.execute(%q{
alter table audios
change record_time_tmp record_time datetime
})
# Add indexes and what not...
end
在这里,您非常熟悉特定于数据库的代码,因此使用直接SQL对我来说似乎是合理的。当然,您可以将其转换为更改列并更新所有调用(可能是使用更新模型类的调用),但我不认为这有什么意义:更改列类型几乎总是涉及特定于数据库的代码,如果您想提高效率,那么迁移就意味着临时桥接。您需要转换UNIX时间戳在插入对象之前删除它们。您可以这样做:DateTime.strptime1493178889,'%s'谢谢,我现在使用的是Time.at1493178889。DateTime.strptime1493178889,'%s'和Time.at1493178889之间有什么区别吗?只是为了更清楚。DateTime.strptime返回一个DateTime对象。Time.at返回一个时间。因为您的列是DATETIME,所以在可能的情况下,您希望使用Ruby DATETIME。
def up
connection.execute(%q{
alter table audios
add record_time_tmp datetime
})
connection.execute(%q{
update audios
set record_time_tmp = from_unixtime(record_time)
})
connection.execute(%q{
alter table audios
drop column record_time
})
connection.execute(%q{
alter table audios
change record_time_tmp record_time datetime
})
# Add indexes and what not...
end