使用 delete_all/delete 删除 rails 个活动记录违反了外键约束
Deleting rails active records with delete_all/delete violates foreign key constraint
我有一个活动记录关联设置:dependent => :destroy,它按预期工作。
然后我发现由于性能原因我需要使用 delete 而不是 destroy,所以我只是根据关联将 destroy 更改为 delete_all/delete。
当我尝试删除时:
shop.shop_snapshots.completed.last.delete
我收到错误消息:
ActiveRecord::InvalidForeignKey (PG::ForeignKeyViolation: ERROR: update or delete on table "shop_snapshots" violates foreign key constraint "fk_rails_c24b24adaf" on table "inventory_items"
但这是为什么呢 - 我相信我在快照上的设置是正确的:
has_many :inventory_items, :dependent => :delete_all
它对销毁有效,所以我做错了什么?
谢谢
/路易丝
需要在迁移级别设置。
像这样:
create_table :childs do |t|
t.references :parent, index: true, foreign_key: {on_delete: :cascade}
t.string :name
t.timestamps null: false
end
在 Postgres 上,您可以在外键本身上使用 CASCADE 选项。
CASCADE specifies that when a referenced row is deleted, row(s)
referencing it should be automatically deleted as well.
- https://www.postgresql.org/docs/9.5/ddl-constraints.html
这通常是在创建 table 时设置的,但您可以通过删除然后重新添加外键约束将其添加到现有的 table:
class AddCascadeToOrderItems < ActiveRecord::Migration[6.0]
def up
remove_foreign_key :order_items, :orders
add_foreign_key :order_items, :orders, on_delete: :cascade
end
def down
remove_foreign_key :order_items, :orders
add_foreign_key :order_items, :orders
end
end
由于这是在数据库级别处理的,因此您的模型中不需要配置。
has_many :inventory_items, dependent: :delete_all
同样有效,并且是像 MySQL 这样的农民数据库的唯一选项,但它只会在您调用 .destroy
而不是 .delete
声明关联的模型时被触发因为它是作为模型回调实现的。例如:
class Store < ApplicationRecord
has_many :inventory_items, dependent: :delete_all
end
store = Store.find(1)
store.destroy # triggers callbacks and will delete all assocatiated inventory_items
store.delete # will not trigger callbacks
我有一个活动记录关联设置:dependent => :destroy,它按预期工作。 然后我发现由于性能原因我需要使用 delete 而不是 destroy,所以我只是根据关联将 destroy 更改为 delete_all/delete。
当我尝试删除时:
shop.shop_snapshots.completed.last.delete
我收到错误消息:
ActiveRecord::InvalidForeignKey (PG::ForeignKeyViolation: ERROR: update or delete on table "shop_snapshots" violates foreign key constraint "fk_rails_c24b24adaf" on table "inventory_items"
但这是为什么呢 - 我相信我在快照上的设置是正确的:
has_many :inventory_items, :dependent => :delete_all
它对销毁有效,所以我做错了什么?
谢谢 /路易丝
需要在迁移级别设置。
像这样:
create_table :childs do |t|
t.references :parent, index: true, foreign_key: {on_delete: :cascade}
t.string :name
t.timestamps null: false
end
在 Postgres 上,您可以在外键本身上使用 CASCADE 选项。
CASCADE specifies that when a referenced row is deleted, row(s) referencing it should be automatically deleted as well.
- https://www.postgresql.org/docs/9.5/ddl-constraints.html
这通常是在创建 table 时设置的,但您可以通过删除然后重新添加外键约束将其添加到现有的 table:
class AddCascadeToOrderItems < ActiveRecord::Migration[6.0]
def up
remove_foreign_key :order_items, :orders
add_foreign_key :order_items, :orders, on_delete: :cascade
end
def down
remove_foreign_key :order_items, :orders
add_foreign_key :order_items, :orders
end
end
由于这是在数据库级别处理的,因此您的模型中不需要配置。
has_many :inventory_items, dependent: :delete_all
同样有效,并且是像 MySQL 这样的农民数据库的唯一选项,但它只会在您调用 .destroy
而不是 .delete
声明关联的模型时被触发因为它是作为模型回调实现的。例如:
class Store < ApplicationRecord
has_many :inventory_items, dependent: :delete_all
end
store = Store.find(1)
store.destroy # triggers callbacks and will delete all assocatiated inventory_items
store.delete # will not trigger callbacks