【问题标题】:PG::DependentObjectsStillExist: ERROR: cannot drop table reports because other objects depend on itPG::DependentObjectsStillExist:错误:无法删除表报告,因为其他对象依赖于它
【发布时间】:2023-03-08 14:24:01
【问题描述】:

提供一些背景知识。我是 Ruby on Rails 的新手,我正在创建一个评论网站,用户可以在其中报告评论。我玩弄了一个“可报告的”多态关联,然后报告表格。后来我删除了“报告”表并创建了另一个报告表。早期迁移不允许创建新的报告表迁移,因此我在迁移早期迁移的名称旁边添加了“1”。

20180311071357_create_reports_1.rb
class CreateReports1 < ActiveRecord::Migration[5.0]
  def change
    create_table :reports do |t|
      t.string :reason
      t.text :description
      t.string :email
      t.belongs_to :reportable, polymorphic: true
      t.timestamps
    end
  end
end

快进到现在。我有一段时间没有对 Heroku 进行生产提交,我只是在构建应用程序。当我推送到 heroku 时,出现以下错误-

heroku run rake db:migrate --trace

Running rake db:migrate --trace on ⬢ housereview... up, run.6689 (Free)
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate
   (4.0ms)  SELECT pg_try_advisory_lock(2386658352535867725);
  ActiveRecord::SchemaMigration Load (4.6ms)  SELECT "schema_migrations".* FROM "schema_migrations"

Migrating to DeleteReports1 (20180318091834)
   (1.2ms)  BEGIN
== 20180318091834 DeleteReports1: migrating ===================================
-- drop_table(:reports)
   (2.8ms)  DROP TABLE "reports"
   (2.6ms)  ROLLBACK
   (2.3ms)  SELECT pg_advisory_unlock(2386658352535867725)

rake aborted!

StandardError: An error has occurred, this and all later migrations canceled:

PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
: DROP TABLE "reports"
...
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'

Caused by:
ActiveRecord::StatementInvalid: PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
: DROP TABLE "reports"
/app/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `async_exec'

.......
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'

Caused by:
PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
/app/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `async_exec'

这是我的架构-

ActiveRecord::Schema.define(version: 20180407122611) do

  create_table "locations", force: :cascade do |t|
    t.string "address"
    t.string "street_number"
    t.string "locality"
    t.string "postal_code"
    t.string "country"
    t.string "route"
    t.string "state"
  end

  create_table "notes", force: :cascade do |t|
    t.text     "description"
    t.integer  "report_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.index ["report_id"], name: "index_notes_on_report_id"
  end

  create_table "reports", force: :cascade do |t|
    t.string   "reason"
    t.text     "description"
    t.integer  "user_id"
    t.integer  "review_id"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
    t.datetime "completed_at"
    t.index ["review_id"], name: "index_reports_on_review_id"
  end

  create_table "reviews", force: :cascade do |t|
    t.string   "title"
    t.string   "duration"
    t.text     "positive"
    t.text     "negative"
    t.integer  "location_id"
    t.integer  "user_id"
    t.integer  "rating_safety"
    t.integer  "rating_neighbour"
    t.integer  "rating_owner"
    t.integer  "rating_school"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "rating_overall"
    t.boolean  "blocked"
    t.index ["location_id"], name: "index_reviews_on_location_id"
  end

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "",    null: false
    t.string   "encrypted_password",     default: "",    null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,     null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "unconfirmed_email"
    t.datetime "created_at",                             null: false
    t.datetime "updated_at",                             null: false
    t.boolean  "admin",                  default: false
    t.string   "first_name"
    t.string   "last_name"
    t.string   "locality"
    t.string   "state"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

我尝试了(几乎)一切来解决这个问题。到目前为止我尝试过的以下事情- - 删除生产应用程序,然后恢复 pgbackup - 删除生产应用程序,然后尝试执行新的“git push heroku master”,然后执行“heroku run rake db:migrate” - 尝试了 drop table 命令,然后再次推送代码并 rake db:migrate - 在 pgsql 中尝试了“DROP TABLE if exists reports cascade;”

以上都没有运气。 该应用程序在 dev (SQLite) 中运行良好,但 heroku 不允许我 rake db:migrate。

提前致谢!

【问题讨论】:

    标签: ruby-on-rails postgresql heroku drop-table


    【解决方案1】:

    Notes 表包含 report_id 作为外键,因此您无法删除报告表。您可以使用dependent: :destroy 在 report.rb 文件中更改以下行

    has_many :notes
    

    到

    has_many :notes, dependent: :destroy 
    

    【讨论】:

    • @FA 您可以生成一个迁移以从 notes 表中删除 report_id 并在删除表迁移之前创建此迁移。因此此迁移将从注释表中删除 report_id,然后您可以删除报告表
    【解决方案2】:

    您还有创建notes 表的迁移吗?我猜想该迁移中的create_table :notes 与您在db/schema.rb 中看到的不完全匹配。

    无论如何,您的问题是 notes.report_id 通过数据库内的外键引用 reports.id。这个外键可能是由t.references :report, foreign_key: true 在迁移中创建的,以确保引用完整性(即数据库将确保notes.report_id 中的任何值引用reports 表中的某些内容)。此外键约束阻止您删除 reports 表,因为这会违反 notes.report_id 上的约束。

    我认为您根本不想删除 reports 表。相反,您想让 Heroku 中的 reports 表与 schema.rb 所说的相匹配。迁移并不意味着永远持续下去,所以继续删除有问题的迁移并编写一个新迁移,使 Heroku 中的 reports 表与 schema.rb 所说的内容同步。

    清理完这些烂摊子后,您需要做两件事:

    1. 不再重命名迁移。删除旧迁移并不时添加新迁移。如果您想保留旧的迁移但将其名称用于其他内容,请在 new 迁移上加上后缀,但实际上,没有理由永远保留旧迁移。

      李>
    2. 在本地开发环境中安装 PostgreSQL。您应该始终使用相同的堆栈进行开发、测试和部署。数据库之间存在如此多的差异,ActiveRecord 无法保护您免受在三种环境中使用不同数据库的影响,这简直是一种疯狂,只不过是通往痛苦的捷径。

    【讨论】:

    • 最后两个技巧是金子。我小 6 个月的我需要早点和你聊天。我想我正在理解我所犯的错误,如果我错了,请纠正我。 1)我创建了一个reports 表,然后创建了一个notes 表。 2) reports 和 notes 具有一对多关联。 3)我推到 Heroku。 4)然后我在开发环境中删除了我的reports 表。 5) 然后我重新创建了reports 表。 6) Heroku push 现在显示错误,因为notes 表是指以前的报告表? 解决方案- 删除report_id 并在notes 表中重新创建report_id 列?
    • 这听起来很对。如果您不关心数据,那么删除 notes.report_id 列也会删除 FK。您可以在迁移之前删除reports 表。
    • 还是没有运气。得到同样的错误。我已经删除了 reports 和 notes 表。仍然出现此错误-== 20180318091834 DeleteReports: migrating ==================================== -- drop_table(:reports) (2.9ms) DROP TABLE "reports" (0.6ms) ROLLBACK PG::DependentObjectsStillExist: ERROR: cannot drop table reports because other objects depend on it DETAIL: constraint fk_rails_cfc8432c20 on table notes depends on table reports
    • 您可以手动 connection.execute('alter table notes drop constraint fk_rails_cfc8432c20') 作为最后的手段。您还可以删除有问题的迁移,查看生产中的表结构,然后添加新的迁移以同步它们。
    猜你喜欢
    • 1970-01-01
    • 2017-04-14
    • 2018-09-01
    • 2016-05-22
    • 2020-12-27
    • 1970-01-01
    • 2021-05-27
    • 2018-12-17
    • 1970-01-01
    相关资源
    最近更新 更多