为什么ActiveRecord提供.delete_all而不是.truncate?

时间:2011-10-14 20:08:58

标签: ruby-on-rails activerecord

我必须手动执行SQL以使用TRUNCATE命令,这似乎很奇怪。 DHH正在保护我免受伤害吗?

4 个答案:

答案 0 :(得分:10)

在某些数据库上使用TRUNCATE不会运行触发器。对每行使用DELETE仍会运行触发器。 TRUNCATE也无法回滚,因此如果您在事务中执行了.destroy_all,即使您尝试回滚,它也会清除所有数据。

所以,是的,你受到了截断效果的保护。

答案 1 :(得分:3)

假设您使用的是MySQL或Postgre而不是SQlite3(它不支持TRUNCATE),您可以将以下方法添加到模型中。

def self.truncate
  self.connection_pool.with_connection { |c| c.truncate(table_name) }
end

请注意,这不会调用ActiveRecord回调。有更好的方法可以将代码绑定到特定的数据库实现,但这甚至比自己编写SQL更好。

答案 2 :(得分:1)

TRUNCATE有很多用例,在我看来,这里给出的答案非常不足。以Postgres为例:

  • TRUNCATE在某些RDBMS中肯定是事务安全的,正如jsears所述。它可以回滚,至少在Postgres中。是不是Rails应该是数据库不可知的并允许这样的事情?
  • TRUNCATE还会在Postgres中执行BEFORE TRUNCATEAFTER TRUNCATE次触发器。如果您希望在DELETE触发TRUNCATE触发器,那就是您的设计错误!
  • TRUNCATE执行速度远远快于DELETE,特别是对于大型数据集,因为它只是一个简短的DDL语句。
  • 在Postgres' MVCC架构,TRUNCATE删除所有索引和表膨胀。

由于这些原因,Rails不支持TRUNCATE让我感到很疯狂。不,我不认为给出的理由是好的。

答案 3 :(得分:-3)

查看Model.destroy_all和活动记录:dependent => :破坏关系。如果您未指定:dependent => :destory,一些默认设置是将关系设置为null但不销毁记录。