我读了很多关于它的内容,但仍然无法摆脱数据库中的一个表: 我没有创建此表的迁移。 但是我认为该表来自acts_as_votable gem的先前安装。 但是我可能已经手动删除了此迁移... 我尝试了drop_table,如下所示,但它不起作用。 即使我有此迁移文件,投票表仍然 ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我在本地环境中的 postgres 数据库中创建了一个“campaigns”表。 我从未提交过更改,因此从未将其推送到 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'
我知道它正在尝试为一个它从来不知道存在的表运行删除表迁移,但我不确定如何处理这个问题。
我尝试删除删除表迁移,推送到生产并运行它,但它仍然尝试运行该迁移。
回滚该提交后,我一直在考虑在重新创建表的21041211003219_drop_campaigns_table
迁移之前手动创建带有21041211003219_drop_campaigns_table
的新迁移,但随后我觉得我将保留本地 postgres 数据库中存在的表(因为21041211003219_drop_campaigns_table
已经在本地运行)。
我是否继续手动创建,然后尝试重新运行删除迁移?
有人可以就这里的最佳行动方案向我提出建议吗?
您可以通过将if_exists: true
添加到drop_table
来关闭错误PG::UndefinedTable: ERROR: table "campaigns" does not exist
删除已经不存在的表时:
def up
drop_table(:campaigns, if_exists: true)
end
这个选项的文档很少,但自 2015 年初以来就存在于 Rails 中,我认为它比手动编写 SQL 更干净,因为它还处理与各种数据库适配器的兼容性。
只需删除有问题的迁移,然后继续做更有趣的事情。 显然,该表没有“创建表”迁移,因此“删除表”迁移无权存在。 如果你真的不想删除迁移,你可以使用原始 SQL 重写它:
def up
connection.execute 'drop table if exists campaigns'
end
if exists
完全符合您的想法:它仅在表存在时才尝试删除该表。
关于这个东西:
我认为您不应该删除迁移,以便将来在该项目上工作的任何其他人都可以运行它们并拥有准确的数据库。
迁移旨在将应用程序的现有实例从状态 A 获取到状态 B。 如果您正在启动一个新实例,您将使用schema.rb
(或structure.sql
)来初始化应用程序,并且不需要迁移。 此外,一旦迁移已应用于应用程序的每个实例,除非您想尝试倒退,否则真的不再需要迁移。 我倾向于在发布几周后清除旧的迁移,以保持混乱。
if_exists
不适用于 rails 4.2 和 PG 9.6。 感谢@MartinSommer 提到table_exists?
. 对于后代,这是我使用的语法,读起来更清晰。
drop_table :campaigns if table_exists?(:campaigns)
当您删除迁移文件并希望删除相应的表时,例如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
普通 SQL
def down
execute <<~SQL
DROP TABLE IF EXISTS campaigns;
SQL
end