postgresql - Rails 4,迁移以将列的数据类型从 daterange 更改为 tsrange,导致 PG::DatatypeMismatch:错误:

标签 postgresql activerecord ruby-on-rails-4 range postgresql-9.2

我正在尝试使用 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. A USING 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)。当然,由于(明显)缺少从 daterangetsrange 的内置转换,这变得更加复杂,但是如果你拉daterangeupper 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 表达式。查看范围的左端和右端是开还是闭。


顺便说一句,whenPostgreSQL keyword所以它不是标识符的最佳选择,每次在 SQL 片段中引用该列时都必须说 "when",这可能会让人厌烦。我建议为该列使用不同的名称,这样您就不必担心引用问题。

关于postgresql - Rails 4,迁移以将列的数据类型从 daterange 更改为 tsrange,导致 PG::DatatypeMismatch:错误:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20820997/

相关文章:

postgresql - RETURN NEXT 出错

mysql - ActiveRecord 在我的代码未指定的列上添加 DISTINCT

php - 从 Yii2 中的联结表中检索数据

ruby - 只有当电子表格打开文件时 URI 必须是 ascii?

ruby-on-rails - 从 Doorkeeper 提供商的多个应用程序中单点注销

ruby-on-rails - 在 ruby​​ on Rails 中销毁客户/订单

postgresql - 如何确定是否在数据库上启用了postgis?

ruby-on-rails - 在使用 Rails 4.1 的第一个模型上使用带有连接和排序的 pluck

spring - 在 PostgreSQL 中使用 Hibernate 上传图像

mysql - 获取平均值时在 Ruby + Rails 中执行子查询的最佳方法?