开发者

Why does ActiveRecord provide .delete_all and not .truncate?

开发者 https://www.devze.com 2023-04-13 07:30 出处:网络
It seems strange that I have to manually execute SQL to use the TRUNCATE command. Is there something bad about it that DHH is p开发者_StackOverflowrotecting me against?Using TRUNCATE on some databases

It seems strange that I have to manually execute SQL to use the TRUNCATE command. Is there something bad about it that DHH is p开发者_StackOverflowrotecting me against?


Using TRUNCATE on some databases does not run triggers. Using DELETE for each row will still run triggers. TRUNCATE also cannot be rolled back, so if you did a .destroy_all in a transaction, it would erase all the data even if you tried to rollback.

So, yes, you are being protected against the effects of truncate.


Assuming you're using MySQL or Postgre and not SQlite3 (which doesn't support TRUNCATE), you could add the following method to your model.

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

Note that this would not invoke ActiveRecord callbacks. There are better ways to do this that don't tie your code to a specific DB implementation, but even this is better than writing the SQL yourself.


There are many use cases for TRUNCATE, and in my opinion, the answers given here are very insufficient. Using Postgres as an example:

  • TRUNCATE is definitely transaction safe in some RDBMS, as already noted by jsears. It can be rolled back, at least in Postgres. Isn't Rails supposed to be db-agnostic and allow for such things?
  • TRUNCATE will also execute BEFORE TRUNCATE or AFTER TRUNCATE triggers in Postgres. If you are expecting a DELETE trigger to fire on TRUNCATE that's your design fault!
  • TRUNCATE performs far quicker than DELETE especially for large datasets because it's a single short DDL statement.
  • In Postgres' MVCC architecture, TRUNCATE removes all index and table bloat.

For these reasons it's crazy to me that Rails does not support TRUNCATE. No, I don't think the reasons given are good ones.


Take a look at Model.destroy_all and active record : dependent => :destroy relations. If you don't specify :dependent => :destory, some of the defaults is to set relation to null but not destroy the record.

0

精彩评论

暂无评论...
验证码 换一张
取 消