首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Rails 4,迁移以将列的数据类型从daterange更改为tsrange,导致PG::DatatypeMismatch: ERROR:

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

Stack Overflow用户
提问于 2013-12-29 08:45:46
回答 1查看 1.6K关注 0票数 3

我正在尝试使用普通的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 HINT: Specify a USING expression to perform the conversion. : ALTER TABLE "events" ALTER COLUMN "when" TYPE tsrange

我尝试按照提示进行操作,并使用了以下代码

def self.up
  change_column :events, :when, :tsrange, 'tsrange USING CAST(when AS tsrange)'
end

但后来得到了

no implicit conversion of Symbol into Integer

据我所知,使用CAST主要是为了与int一起使用。假设我不想删除列,然后重新创建列,那么您必须指定什么才能将类型从daterange更改为tsrange?

我正在使用

  • Rails 4.0.1
  • ruby-2.0.0-p247
  • psql (9.2.4)

在下面的PR中,Rails 4引入了一些背景、日期范围和范围:https://github.com/rails/rails/pull/7345。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-12-29 09:20:32

USING clause用于指定如何将旧值转换为新值:

可选的USING子句指定如何从旧数据类型计算新列值;如果省略,则默认转换与从旧数据类型转换为新数据类型的赋值转换相同。如果没有从旧类型转换为新类型的隐式类型或赋值类型,则必须提供USING子句。

因此,只要没有从旧类型到新类型的缺省类型转换,就会出现使用。还要注意,USING被指定为USING expression,因此任何表达式(其值的类型正确)都可以与USING一起使用,最常见的是USING CAST(...),但expression可以是几乎任何东西。

希望这能澄清一些关于使用的困惑。

那么ActiveRecord错误是怎么回事呢?嗯,change_column期望在第四个参数中看到一个options散列,但是你发送的是一个字符串。如果你看一下change_column源代码,你会看到像options[:limit]这样的东西,但是String#[]需要整数参数,所以你的字符串参数触发了关于符号的奇怪的抱怨。

没有办法让AR将USING子句添加到change_column生成的ALTER TABLE ... ALTER COLUMN中。如果需要USING子句,则只剩下connection.execute(some_sql)。当然,由于(明显)缺乏从daterangetsrange的内置类型转换,这一点变得更加复杂,但如果使用upper and lower函数拆分daterange,构建必要的表达式并不是很困难:

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",这可能会很累人。我建议对该列使用不同的名称,这样您就不必担心引用。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20820997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档