我从sqlite迁移到Postgres,所以我可以推送到Heroku,并收到一个错误时运行$ Heroku运行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是类型:date,但我通过迁移将其更改为字符串,并且在模式中它目前是字符串。下面的错误是在我将其更改为string之前引用初始迁移和旧数据类型。
然后我在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
我在这里做错了什么?
PostgreSQL中没有string
类型,您需要text
或varchar
。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
在PostgreSQL中是内部相同的(除了varchar(n)
上额外的长度检查),所以除非你特别需要数据库内部的长度限制,否则你通常只会使用text
。