【问题标题】:Rails Postgres Datatype Mismatch - "cannot be cast automatically to type date"Rails Postgres 数据类型不匹配 - “无法自动转换为类型日期”
【发布时间】:2016-08-31 22:52:31
【问题描述】:

我从 sqlite 迁移到 Postgres,所以我可以推送到 Heroku,并在运行 $ heroku run rake db:migrate: 时收到错误:

 ActiveRecord::SchemaMigration Load (0.9ms)  SELECT "schema_migrations".* FROM     "schema_migrations"
Migrating to ChangeCheckIn (20160726015859)
(0.7ms)  BEGIN
== 20160726015859 ChangeCheckIn: migrating      ====================================
-- change_column(:listings, :check_in_date, :date)
 (1.3ms)  ALTER TABLE "listings" ALTER COLUMN "check_in_date" TYPE date
(0.7ms)  ROLLBACK
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::DatatypeMismatch: ERROR:  column "check_in_date" cannot be cast automatically to type date
HINT:  You might need to specify "USING check_in_date::date".
: ALTER TABLE "listings" ALTER COLUMN "check_in_date" TYPE date

当我最初为 :listing 构建模型时,check_in_date 是 type:date,但我通过迁移到字符串将其更改,并且在模式中它当前是字符串。下面的错误是在我将其更改为字符串之前引用了初始迁移和旧数据类型。

然后我根据这个关于 SO 的问题创建了一个新的迁移(下)并收到了一个新错误(下):Rails migrations - change_column with type conversion

change_column :listings, :check_in_date, 'string USING CAST(check_in_date AS string)' 

PG::UndefinedObject: ERROR:  type "string" does not exist

我在这里做错了什么?

【问题讨论】:

    标签: ruby-on-rails postgresql ruby-on-rails-4 heroku rails-activerecord


    【解决方案1】:

    PostgreSQL 中没有string 类型,你需要textvarchar。 SQLite 可以让您摆脱这种情况,因为它认为任何无法识别的类型都是text 的别名。但是,迁移中有 t.string 方法,但它会创建一个 varchar 列,因此您可能只是对术语有一些混淆。

    你想要更像这样的东西:

    change_column :listings, :check_in_date, 'text using cast(check_in_date as text)'
    

    或使用 PostgreSQL 特定的转换:

    change_column :listings, :check_in_date, 'text using check_in_date::text'
    

    请注意,t.string 在迁移中会在数据库中创建一个varchar(255) 列,并且varchar(n)text 在内部是相同的(除了对varchar(n) 的额外长度检查),因此您将通常只使用text,除非您特别需要数据库内的长度限制。

    【讨论】:

    • 在我从 sqlite 切换到 pg 之前,我是否必须对最初是 sqlite 中的字符串的每条记录进行此迁移?
    • 迁移会一次性将整个从一个日期变成一个字符串,该列目前是date,对吧?
    • 抱歉,我不应该选择“记录”这个词。我的意思是,在我的架构中有多个字符串列(check_in_date、check_out_date、hotel、bookingengine 等)。我是否需要为每个这些运行额外的单独迁移以消除我发布的关于 check_in_date 的相同错误?
    • 如果当前类型是字符串,那么您可以为每一列使用'date using cast(... as date)'。如果这引发异常,那么您必须在更改列类型之前修复格式(最好是 YYYY-MM-DD)。
    • 我注意到即使它没有被记录,这种语法也可以工作:change_column :listings, :check_in_date, :text, using: 'check_in_date::text'(在 Rails 6.0.3.4 上测试)
    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 2019-01-16
    • 2016-03-13
    相关资源
    最近更新 更多