【问题标题】:How to delete all data from all tables in Rails?如何从 Rails 中的所有表中删除所有数据?
【发布时间】:2009-07-28 19:14:49
【问题描述】:

我可以通过Post.delete_all 删除我所有的帖子,但是如果我想删除所有帖子、cmets、博客等怎么办?

如何遍历我的所有模型并运行 delete_all 方法?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:
    rake db:reset 
    

    它从迁移中重新创建您的表。

    根据 cmets 的建议,一种更快的方法(但您必须添加新的 rake 任务)是:

    namespace :db do
      desc "Truncate all tables"
      task :truncate => :environment do
        conn = ActiveRecord::Base.connection
        tables = conn.execute("show tables").map { |r| r[0] }
        tables.delete "schema_migrations"
        tables.each { |t| conn.execute("TRUNCATE #{t}") }
      end
    end
    

    回复来自:answer on SO

    【讨论】:

    • 很好,虽然我更喜欢不需要删除和重新创建所有表的方法。
    • just 删除表行的更快、更精确的方法是使用 TRUNCATE 命令:stackoverflow.com/a/6332189/109618
    • 这会在我尝试运行它时引发异常,显然是sqlite doesn't have a TRUNCATE command
    • 除了设置tables,您还可以使用conn.tables 以更不可知的方式获取表格列表。这样它也适用于 postgres。
    【解决方案2】:

    您可以通过以下方式进行更好的控制:

    rake db:drop:all
    

    然后在不运行迁移的情况下创建数据库,

    rake db:create:all
    

    然后运行所有迁移,

    rake db:migrate 
    

    你也可以这样做:

    mysqladmin drop databasename
    

    【讨论】:

    • rake db:drop:all 正是我想要的。谢谢!
    • 警告: 这将删除默认 development 环境中的所有表。使用RAILS_ENV 环境变量进行更精细的控制
    【解决方案3】:

    如果您尝试从代码而不是命令行执行此操作,例如从 Test::Unit::TestCase#teardown 方法,您可以执行任一操作

    class MyTest < Test::Unit::TestCase
    
      def teardown
        ActiveRecord::Base.subclasses.each(&:delete_all)
      end
    
    end
    

    class MyTest < Test::Unit::TestCase
    
      def teardown
        Rake::Task['db:reset'].invoke
      end
    
    end
    

    不过,我警告你:特别也不是很快。如果可以的话,你肯定会更好地使用事务测试。

    【讨论】:

    • 我用 Rails4 试过这个,奇怪的是数据没有被删除
    【解决方案4】:

    如果您只是想从一组新的空表重新开始,您可以首先确保您在 db/schema.rb 中拥有最新的架构定义:

    rake db:schema:dump
    

    然后:

    rake db:schema:load
    

    这具有删除表然后重新创建它们的效果,而无需运行整个迁移电池。

    【讨论】:

    • 它运行了所有迁移
    【解决方案5】:

    在 Rails 6 中,您可以通过 rails db:truncate_all 删除所有数据而不删除任何表。

    如果您想在那之后为您的数据库播种,您也可以使用rails db:seed:replant 截断所有数据和种子数据库

    【讨论】:

    • 请注意任何未来的读者:如果您在数据库中有其他表,即使它们不是基于与您的 Rails 项目相关联的模型,所有这些数据也将被删除。尽管该表没有与项目中的任何 Rails 模型关联,但我通过运行 truncate_all 刚刚丢失了 330GB 的数据。叹息
    【解决方案6】:

    rails db:purge

    最近已在 rails 4.2.0.alpha 的 master 分支中添加到 ActiveRecord

    https://github.com/rails/rails/commit/e2f232aba15937a4b9d14bd91e0392c6d55be58d

    【讨论】:

    • 这给了我我想要的,尽管我想要的与所提出的问题不同。运行rails db:purge 实际上会删除数据库中的所有表(虽然不是数据库本身)。
    【解决方案7】:

    只是删除表行的更快方法是使用 TRUNCATE 命令。

    许多其他答案似乎忽略了删除行和删除表之间的区别。删除表会破坏表数据和模式;这意味着您需要额外的步骤来重新创建表。 Sean McLeary 的回答是我见过的最好的,所以我用它作为起点。但是,我认为最好利用 TRUNCATE 命令,因为它应该更快,并且它还重置自动增量键。此外,使用map 而不是each 会稍微缩短代码。

    namespace :db do
      desc "Truncate all tables"
      task :truncate => :environment do
        conn = ActiveRecord::Base.connection
        tables = conn.execute("show tables").map { |r| r[0] }
        tables.delete "schema_migrations"
        tables.each { |t| conn.execute("TRUNCATE #{t}") }
      end
    end
    

    【讨论】:

    • 为什么要删除“schema_migrations”?
    • nurettin: 严格来说,删除schema_migrations 并不是必不可少的。但是,在截断表之后,您可能已将数据置于无法通过迁移进行导航的状态。因此,删除 schema_migrations 会让 Rails 从已知状态重新开始迁移。
    【解决方案8】:

    Postgres db 接受的答案:

    namespace :db do
      desc "Truncate all tables"
      task :truncate => :environment do
        conn = ActiveRecord::Base.connection
        postgres = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname='public'"
        tables = conn.execute(postgres).map { |r| r['tablename'] }
        tables.delete "schema_migrations"
        tables.each { |t| conn.execute("TRUNCATE \"#{t}\"") }
      end
    end
    

    如果有foreign_key类似ActiveRecord::StatementInvalid (PG::FeatureNotSupported: ERROR: cannot truncate a table referenced in a foreign key constraint)的错误

    那么,CASCADE 选项会有所帮助。

    tables.each { |t| conn.execute("TRUNCATE \"#{t}\" CASCADE") }
    

    【讨论】:

      【解决方案9】:

      如果您想在应用程序或 Rails 控制台中使用数据时只删除数据而不触及表格:

      Rails.application.eager_load!
      ActiveRecord::Base.connection.disable_referential_integrity do
        ApplicationRecord.descendants.each do |model|
          model.delete_all
        end
      end
      

      使用此代码,您不必费心手动引用您的模型和/或使用外键约束(感谢 disable_referential_integrity)。
      ApplicationRecord.descendants 只返回真正的应用程序模型,这与 ActiveRecord::Base.descendants 不同(不再有 ApplicationRecord、schema_migrations 和 ar_internal_metadata)。

      【讨论】:

        【解决方案10】:

        这也适用于 Rails 4

        (ActiveRecord::Base.connection.tables - ['schema_migrations']).each do |table|
            table.classify.constantize.destroy_all
        end
        

        【讨论】:

        • 这对我来说很好用,Rails 4,sqlite。巧妙的把戏。但是请注意,当它遇到我的 many_to_many 表时抛出了一个错误,该表没有得到 AR 模型的支持。我必须以与 schema_migrations 相同的方式从 tables 数组中删除它。
        【解决方案11】:

        您可以列出种子文件 (seeds.rb) 中的所有模型,然后简单地运行

        rake db:seed
        

        种子文件将如下所示:

        Model1.delete_all
        Model2.delete_all
        Model3.delete_all
        Model4.delete_all
        Model5.delete_all
        Model6.delete_all
        Model7.delete_all
        

        ...

        rake db:reset 对你的工作来说太过分了。这将完全杀死您的数据库并从头开始重建它,运行所有迁移等。运行种子命令更快。

        【讨论】:

          【解决方案12】:

          由于没有提及database_cleaner gem,我们在 Stack Overflow 上失职了:

          Database Cleaner 是一组用于在 Ruby 中清理数据库的策略。 最初的用例是在测试期间确保干净的状态。每个策略 是少量的代码,但它是任何 ruby​​ 应用程序中通常需要的代码 那是用数据库进行测试。

          通过“策略”,Mabey 先生的意思是:截断、事务和删除。

          支持 ActiveRecord、DataMapper、Sequel、MongoMapper、Mongoid 和 CouchPotato。

          这是来自Database Cleaner README的快速代码sn-p:

          require 'database_cleaner'
          DatabaseCleaner.strategy = :truncation
          
          # then, whenever you need to clean the DB
          DatabaseCleaner.clean
          

          【讨论】:

            【解决方案13】:
            # fast truncation of all tables that need truncations (select is 10x faster then truncate)
            # http://grosser.it/2012/07/03/rubyactiverecord-fastest-way-to-truncate-test-database/
            def truncate_all_tables
              connection = ActiveRecord::Base.connection
              connection.disable_referential_integrity do
                connection.tables.each do |table_name|
                  next if connection.select_value("SELECT count(*) FROM #{table_name}") == 0
                  connection.execute("TRUNCATE TABLE #{table_name}")
                end
              end
            end
            

            【讨论】:

              【解决方案14】:

              我知道这是一个老问题,但我认为这可能对某人有所帮助。这是从数据库中清除所有数据的一种非常快速的方法。

              tables = []
              ActiveRecord::Base.connection.execute("show tables").each { |r| tables << r[0] }
              tables = tables - ["schema_migrations"]
              tables.each do |table|
                ActiveRecord::Base.connection.execute("DELETE FROM #{table} WHERE 1 = 1")
              end
              

              我在 after(:all) 块的某些规范中使用了这种技术。这比用于清除、迁移、重置数据库的任何 Rails rake 任务都更快、更有效。

              顺便说一句:我很确定如果您在数据库端强制执行外键约束,这可能会失败。

              【讨论】:

                【解决方案15】:

                我的 50 美分,用于清理数据库并能够再次运行迁移(以防您无法删除数据库,例如 AWS RDS):

                # get connection
                conn = ActiveRecord::Base.connection
                # find all tables needed to be removed
                tables = conn.execute("SELECT * FROM pg_catalog.pg_tables WHERE schemaname='public' AND tablename<>'schema_migrations'").to_a.map { |r| r['tablename'] }
                # remove all tables except schema_migrations
                tables.each { |t| conn.execute("DROP TABLE #{t}") }
                # clean migrations table
                conn.execute("TRUNCATE TABLE schema_migrations")
                

                现在您可以运行rake db:migrate 让您的数据库处于干净状态。

                【讨论】:

                  【解决方案16】:

                  以@Vlad Zloteanu 的回答为基础,这是一个删除所有表的版本,同时保留用户记录和登录会话以及一些元信息。随意调整表格列表以满足您的要求。

                  # lib/tasks/db/truncate.rake
                  
                  namespace :db do
                    desc 'Truncate all tables except users state and meta'
                    task truncate: :environment do
                      conn = ActiveRecord::Base.connection
                      tables = conn.tables - %w[
                        sessions
                        users
                        roles
                        users_roles
                        schema_migrations
                        ar_internal_metadata
                      ]
                      tables.each { |t| conn.execute("TRUNCATE #{t}") }
                  
                      puts "Truncated tables\n================\n#{tables.sort.join("\n")}"
                    end
                  end
                  

                  【讨论】:

                    【解决方案17】:

                    如果您想删除所有表并使用您可以使用的默认值重新初始化。

                    rails db:bootstrap
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-03-15
                      • 2011-03-05
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-06-06
                      相关资源
                      最近更新 更多