我创建了一个'广告系列'在我的本地环境中的postgres数据库中的表。我从未犯过这些变化,因此从未将其推到heroku上。
当我改变主意需要该表时,我愚蠢地手动删除了迁移(我知道现在永远不会这样做)。但是,由于迁移已经运行,我创建了21041211003219_drop_campaigns_table
迁移以从本地数据库中删除表。
现在,当我在制作中运行heroku run rake db:migrate
时,我收到以下错误:
Migrating to DropCampaignsTable (20141211003219)
== 20141211003219 DropCampaignsTable: migrating ===============================
-- drop_table(:campaigns)
PG::UndefinedTable: ERROR: table "campaigns" does not exist
: DROP TABLE "campaigns"
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: table "campaigns" does not exist
: DROP TABLE "campaigns"/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `async_exec'
/app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.1.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:128:in `block in execute'
我知道它正在尝试为一个从未知道存在的表运行drop table迁移,但我不确定如何处理它。
我尝试删除drop table迁移,推送到生产并运行它但仍尝试运行该迁移。
在回滚该提交后,我一直在考虑手动创建一个新的迁移,其中包含重新创建表的21041211003219_drop_campaigns_table
迁移之前的日期戳,但后来我觉得我会成为留下本地postgres db中存在的表(因为21041211003219_drop_campaigns_table
已在本地运行)。
我是否继续手动创建,然后尝试重新运行drop migration?
有人可以告诉我这里最好的行动方案吗?
答案 0 :(得分:22)
通过将PG::UndefinedTable: ERROR: table "campaigns" does not exist
添加到if_exists: true
,您可以在删除已存在的表时关闭错误drop_table
:
def up
drop_table(:campaigns, if_exists: true)
end
这个选项很少记录,但存在于Rails since early 2015中,我认为它比手工编写SQL更清晰,因为它还处理与各种数据库适配器的兼容性。
答案 1 :(得分:10)
只需删除有问题的迁移,然后继续进行更多有趣的事情。显然,该表没有“创建表”迁移,因此“删除表”迁移无权存在。如果您确实不想删除迁移,可以使用原始SQL重写它:
def up
connection.execute 'drop table if exists campaigns'
end
if exists
完全符合您的想法:它只会尝试删除表格。
关于这个东西:
我认为您不应该删除迁移,以便将来在该项目上工作的其他任何人都可以运行它们并拥有准确的数据库。
迁移旨在将应用程序的现有实例从状态A获取到状态-B。如果您要开始一个新实例,那么您将使用schema.rb
(或structure.sql
)来初始化应用程序,并且不需要迁移。此外,一旦迁移已应用于应用程序的每个实例,除非您想尝试向后移动,否则不再需要迁移。我倾向于在发布后几周清除旧的迁移,以防止混乱。
答案 2 :(得分:2)
if_exists
在Rails 4.2和PG 9.6上不适合我。感谢@MartinSommer提到table_exists?
。为了后代,这是我使用的语法,读起来更简洁一些。
drop_table :campaigns if table_exists?(:campaigns)
答案 3 :(得分:0)
普通SQL
def down
execute <<~SQL
DROP TABLE IF EXISTS campaigns;
SQL
end
答案 4 :(得分:0)
要删除迁移文件时,要删除相应的表,例如student_items
,有两种方法:
简单方法:将迁移文件还原到存档并运行
rails db:rollback
创建迁移:
rails g migration DropStudentItemTable
并将此代码添加到迁移文件中:
class DropStudentItemTables < ActiveRecord::Migration[6.0]
def down
table_exists?(:student_items) ? drop_table(:student_items) : nil
end
end