postgresql Rails:删除级联 vs 依赖销毁

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12556614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 00:20:00  来源:igfitidea点击:

Rails: delete cascade vs dependent destroy

ruby-on-railspostgresqlreferential-integrity

提问by apotry

Assuming I have two tables: usersand orders. A user has many orders, so naturally there is a foreign key user_id in my orders table.

假设我有两个表:usersorders。一个用户有很多订单,所以我的订单表中自然会有一个外键user_id。

What is the best practice in rails (in terms of speed, style and referential integrity) to ensure that if a user is deleted, all dependent orders are also deleted? I am considering the following options:

rails 中的最佳实践是什么(在速度、样式和参照完整性方面),以确保如果删除一个用户,所有依赖的订单也会被删除?我正在考虑以下选项:

Case 1. Using :dependent => :destroyin the user model

案例 1.:dependent => :destroy在用户模型中使用

Case 2. Defining the table orders in postgres and writing

案例二:postgres中定义表顺序并写入

user_id integer REFERENCES users(id) ON DELETE CASCADE

Is there any reason why I should use Case 1? It seems that Case 2 is doing all I want it to do? Is there are difference in terms of execution speed?

我有什么理由应该使用案例 1?似乎案例 2 正在做我想要它做的所有事情?执行速度有区别吗?

回答by Peter Brown

It really depends on the behavior you want. In case 1, destroy will be called on each associated order, and therefor so will the ActiveRecord callbacks. In case 2, these callbacks are not triggered, but it will be way faster and guarantees referential integrity.

这真的取决于你想要的行为。在第 1 种情况下,将在每个关联订单上调用 destroy ,因此ActiveRecord 回调也会调用。在情况 2 中,不会触发这些回调,但它会更快并保证参照完整性。

In an application's infancy, I'd recommend going with :dependent => :destroybecause it lets you develop in a way that is independent of the database. Once you start to scale, you should start doing it in the database for performance/integrity reasons.

在应用程序的初期,我建议使用:dependent => :destroy它,因为它可以让您以独立于数据库的方式进行开发。一旦开始扩展,出于性能/完整性的原因,您应该开始在数据库中进行扩展。

回答by WiredIn

has_many :orders, dependent: :destroy

has_many :orders, dependent: :destroy

  • Safest option for automatically maintaining data integrity.
  • You have polymorphic associations, and do not want to use triggers.
  • 自动维护数据完整性的最安全选项。
  • 您有多态关联,并且不想使用触发器。


add_foreign_key :orders, :users, on_delete: :cascade(in database migration)


add_foreign_key :orders, :users, on_delete: :cascade(在数据库迁移中)

  • You are not using any polymorphic associations or you want to use triggers for each polymorphic association.
  • 您没有使用任何多态关联,或者您想为每个多态关联使用触发器。


has_many :orders, dependent: :delete_all


has_many :orders, dependent: :delete_all

  • Only use when the has_many is a leaf node on your association tree (i.e. the child does not have another has_many association with foreign key references)
  • 仅当 has_many 是关联树上的叶节点时才使用(即子节点与外键引用没有另一个 has_many 关联)

回答by f1sherman

I would use option 1. While it may work, I can see a number of issues with option 2:

我会使用选项 1。虽然它可能有效,但我可以看到选项 2 存在许多问题:

  1. ActiveRecord will be unaware that these records were deleted, which could lead to unstable behavior
  2. it would be unclear to anyone reading the code that deleting a user means that all their orders will also be deleted
  3. any destroyhandlers on Order would not fire
  1. ActiveRecord 不会意识到这些记录已被删除,这可能会导致行为不稳定
  2. 任何阅读代码的人都不清楚删除用户意味着他们的所有订单也将被删除
  3. destroyOrder 上的任何处理程序都不会触发

Certainly I would expect option 2 to be faster, but it's up to you if the trade-offs are worth it. Is deletion of a user a common operation in your application?

当然,我希望选项 2 更快,但是否值得权衡取舍取决于您。删除用户是您应用程序中的常见操作吗?

Another option would be to use :dependent => :delete_all. This would be faster than :dependent => :destroyand avoid drawbacks 1 and 2 above. See herefor more details.

另一种选择是使用:dependent => :delete_all. 这将比:dependent => :destroy上述缺点 1 和 2更快并避免上述缺点。请参阅此处了解更多详情。