【问题标题】:Truncate table(s) with rails console使用 rails 控制台截断表
【发布时间】:2012-10-21 20:04:20
【问题描述】:

我有这个测试数据库,到现在为止,里面塞满了垃圾。现在我在 Rails 控制台中完成了一些 Table.destroy_all 命令,它删除了所有记录和依赖项,这很棒。然而;我想截断所有内容,以便 ID 等再次从 1 开始。 Rails 3有什么办法吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 truncate rails-console


    【解决方案1】:

    只需在下一次测试运行时重建数据库(这将在删除后自动发生)。

    rake db:drop RAILS_ENV=test

    【讨论】:

      【解决方案2】:

      仅当您需要重新创建整个数据库时,接受的答案才有效。
      删除单个表(带有回调)并让 ID 从 1 开始:

      Model.destroy_all # Only necessary if you want to trigger callbacks.
      ActiveRecord::Base.connection.execute("TRUNCATE #{table_name} RESTART IDENTITY")
      

      如果您使用的是 Sqlite,它不支持截断,请执行以下操作:

      Model.destroy_all # Only necessary if you want to trigger callbacks.
      ActiveRecord::Base.connection.execute("Delete from #{table_name}")
      ActiveRecord::Base.connection.execute("DELETE FROM SQLITE_SEQUENCE WHERE name='#{table_name}'")
      

      【讨论】:

      • 当一个表应该被截断时你的答案是正确的(我感谢你)我选择了 Yam Marcovic 的答案作为接受的答案,因为我确实要求截断“一切”。
      • 感谢您的投票。问题中并不清楚整个数据库要求!仅供参考, rake db:drop 将删除数据库。如果要求只是截断所有表,您可以运行 ActiveRecord::Base.connection.tables.collect{|table_name| ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")}。虽然它可能不会处理回调,但我想这不是必需的,因为我们正在截断所有表。
      • destroy_all 将对每条记录调用destroy,这与截断表完全不同。来自 Docs:# 通过实例化每个记录并调用其 +destroy+ 方法来销毁匹配 +conditions+ 的记录。 # 执行每个对象的回调(包括 :dependent 关联选项和 # +before_destroy+/+after_destroy+ Observer 方法)。返回 # 个被销毁的对象集合;每个都将被冻结,以 # 反映不应进行任何更改(因为它们不能 # 持久化)。
      • 在 Postgres 中,第二条命令实际上并没有重置 ID 列的自动增量值。为此,您需要“TRUNCATE table_name RESTART IDENTITY”)。见stackoverflow.com/a/7610991/271454
      • 澄清一下:对于 MySQL/MariaDB:ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}") 对于 PostgreSQL:ActiveRecord::Base.connection.execute("TRUNCATE #{table_name} RESTART IDENTITY")
      【解决方案3】:

      你也可以rake db:rollback STEP=3 RAILS_ENV=test

      其中 3 表示您在 db/migrate 中的迁移次数。例如:如果我有

      db/migrate
      20140121065542_create_users.rb
      20140121065710_create_profiles.rb
      20140121065757_create_articles.rb
      20140121065900_create_comments.rb
      20140121065929_create_categories.rb
      

      所以我总共要删除 5 个迁移。如果我这样做rake db:rollback STEP=5 RAILS_ENV=test,所有表都将从我的 TEST 数据库中删除,如果我删除 RAILS_ENV=test,那么所有 ENVIRONNMENT(生产、测试​​、开发)表都将被删除,它还​​会从它的 db/shema.rb 文件中清除迁移数据。

      【讨论】:

        【解决方案4】:

        rake db:reset 将执行rake db:drop db:setup。换句话说,删除数据库并重新设置数据库。

        Source

        【讨论】:

        • 这样做会丢失重要的数据,强烈不推荐。
        • 原来的问题是关于如何删除数据库中的所有数据。
        • 原始问题的标题是“使用 rails 控制台截断表”——可能不需要删除/重置整个数据库。
        【解决方案5】:

        (聚会有点晚了,我知道)

        在控制台中要求这样做:

        2.1.2 :001 > Post.all.each do |post|
        2.1.2 :002 >   post.destroy!
        2.1.2 :003 > end
        

        同样有效...

        这实质上是遍历所有帖子并销毁它们。虽然它不会改变你的自动增量值......

        同样的逻辑也适用于 Rails 3(尽管我使用的是 Rails 4)

        【讨论】:

        • 1.不要使用each,使用find_each。它确保您不会在一次查询中获得十亿条记录 2. 如果您只需要从数据库中删除记录(不运行任何回调),请不要使用循环。就做Post.delete_all
        • 原帖是关于如何使用 Rails 将自动索引重置为零(截断)数据库表。这个答案只删除记录
        • 1.这可能需要几个小时才能完成,因为您要逐条删除记录。 2. 这不会重置 SQL 中的任何序列,3. all.each 会将所有帖子加载到内存中......所以如果你有百万条记录,它可以提高你的应用性能
        【解决方案6】:

        这对我有用 - ActiveRecord::Base.connection.execute("TRUNCATE table_name")

        【讨论】:

        • 最好和最简单的答案
        【解决方案7】:

        假设您使用的是 MySQL 或 Postgre 而不是 SQlite3(不支持 TRUNCATE),您可以执行以下操作:

        MyModel.connection_pool.with_connection { |c| c.truncate(MyModel.table_name) }
        

        请注意,这不会调用 ActiveRecord 回调。

        【讨论】:

          【解决方案8】:
          Model.connection.truncate(Model.table_name)
          

          【讨论】:

          • 自 Rails 4.2.1 起
          【解决方案9】:

          我使用下面的代码来截断所有表格

          ActiveRecord::Base.establish_connection
          ActiveRecord::Base.connection.tables.each do |table|
            next if table == 'schema_migrations'
          
            case ActiveRecord::Base.connection.adapter_name.downcase.to_sym
              when :mysql2 , :postgresql
                ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
                ActiveRecord::Base.connection.execute("TRUNCATE #{table} RESTART IDENTITY")
              when :sqlite
                ActiveRecord::Base.connection.execute("DELETE FROM #{table}")
            end
          end
          

          【讨论】:

            【解决方案10】:

            Rails 6.0+ 添加新方法:truncate_tables

            ActiveRecord::Base.connection.truncate_tables([:table1_name, :table2_name])
            

            https://stackoverflow.com/a/68618256/7438710

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-05-01
              • 2015-03-06
              • 2020-05-28
              • 1970-01-01
              • 2017-04-09
              • 1970-01-01
              • 1970-01-01
              • 2014-10-16
              相关资源
              最近更新 更多