我正在尝试使用 vanilla Rails 迁移将 daterange 类型的列更改为 tsrange(我意识到我需要时间和日期)
def self.up
change_column :events, :when, :tsrange
end
运行 rake db:migrate
后错误是
PG::DatatypeMismatch: ERROR: column "when"cannot be cast automatically to type tsrange
提示:指定一个 USING 表达式来执行转换。
: ALTER TABLE "events"ALTER COLUMN "when"TYPE tsrange
我尝试按照提示使用以下内容
def self.up
change_column :events, :when, :tsrange, 'tsrange USING CAST(when AS tsrange)'
end
然后得到了
没有将 Symbol 隐式转换为 Integer
据我所知,USING CAST 主要用于整数。假设我不想删除然后重新创建该列,您必须指定什么才能将类型从 daterange 更改为 tsrange?
我正在使用
- 导轨 4.0.1
- ruby-2.0.0-p247
- psql (9.2.4)
一些背景、daterange 和 tsrange 在以下 PR 中被引入 Rails 4:https://github.com/rails/rails/pull/7345 .谢谢。
最佳答案
USING clause用于指定如何将旧值转换为新值:
The optional
USING
clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. AUSING
clause must be provided if there is no implicit or assignment cast from old to new type.
所以只要没有从旧类型到新类型的默认转换,USING 就会出现。另请注意,USING 被指定为 USING expression
,因此任何表达式(其值属于正确类型)都可以与 USING 一起使用,最常见的是 USING CAST(...)
但 expression
几乎可以是任何东西。
希望这能消除一些关于 USING 的困惑。
那么ActiveRecord错误是怎么回事呢?嗯,change_column
期望在第四个参数中看到 options
散列,但您发送的是字符串。如果您查看 change_column
源代码,您会看到类似 options[:limit]
的内容,但是 String#[]
需要整数参数,所以你的字符串参数会触发关于符号的奇怪提示。
据我所知,没有办法让 AR 将 USING 子句添加到 change_column
生成的 ALTER TABLE ... ALTER COLUMN
中。如果您需要 USING 子句,这将留下 connection.execute(some_sql)
。当然,由于(明显)缺少从 daterange
到 tsrange
的内置转换,这变得更加复杂,但是如果你拉daterange
与 upper
and lower
分开功能:
connection.execute(%q{
alter table events
alter column "when"
type tsrange using tsrange(lower("when"), upper("when"))
})
您可以在此处看到表的变化:http://sqlfiddle.com/#!15/fb047/2
假设您使用默认的半开区间 ([...)
) 作为您的范围;如果您的范围不是在左侧关闭而在右侧打开,那么您将不得不使用 other range functions 构建更复杂的 USING 表达式。查看范围的左端和右端是开还是闭。
顺便说一句,when
是 PostgreSQL keyword所以它不是标识符的最佳选择,每次在 SQL 片段中引用该列时都必须说 "when"
,这可能会让人厌烦。我建议为该列使用不同的名称,这样您就不必担心引用问题。
关于postgresql - Rails 4,迁移以将列的数据类型从 daterange 更改为 tsrange,导致 PG::DatatypeMismatch:错误:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20820997/