Usunięcie wszystkich rekordów w tabeli bazy danych

Odpowiedzi:

253

Jeśli szukasz sposobu na to bez SQL, powinieneś być w stanie użyć delete_all.

Post.delete_all

lub z kryteriami

Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"

Więcej informacji znajdziesz tutaj .

Rekordy są usuwane bez ich wcześniejszego ładowania, co czyni je bardzo szybkimi, ale psuje funkcjonalność, taką jak pamięć podręczna liczników, która zależy od kodu szyn, który ma być wykonany po usunięciu.

HakonB
źródło
13
Warto zauważyć, że jeśli masz skojarzenia z: depend =>: niszcz lub czymkolwiek, co musi zostać wyczyszczone po usunięciu, prawdopodobnie będziesz chciał Post.destroy_all - chociaż jest znacznie wolniejszy. Zobacz apidock.com/rails/ActiveRecord/Base/destroy_all/class
Michael
Ta odpowiedź zakłada, że ​​tabela ma skojarzony z nią model. OP nie określił tego - co jeśli tabela jest stołem łączenia?
Toby 1 Kenobi
1
@BradWerth, niezależnie od tego, czy niektórzy uważają to za dobry lub zły styl, mówię tylko, że jest możliwe, aby baza danych Railsów zawierała tabele, które nie są ActiveRecordmodelami. Pytanie dotyczy usunięcia rekordu z „tabeli”, a ja tylko wskazuję lub założenie zawarte w odpowiedzi.
Toby 1 Kenobi
Mam takie samo zapytanie jak @ Toby1Kenobi.
nbsamar
30

Aby usunąć przez SQL

Item.delete_all # accepts optional conditions

Aby usunąć, wywołując metodę zniszczenia każdego modelu (kosztowna, ale zapewnia wywołanie zwrotne)

Item.destroy_all # accepts optional conditions

Wszystko tutaj

lebreeze
źródło
23

jeśli chcesz całkowicie opróżnić bazę danych, a nie tylko usunąć model lub modele do niej dołączone, możesz:

rake db:purge

możesz to również zrobić w testowej bazie danych

rake db:test:purge
KensoDev
źródło
6

Jeśli masz na myśli usunięcie każdej instancji wszystkich modeli, użyłbym

ActiveRecord::Base.connection.tables.map(&:classify)
  .map{|name| name.constantize if Object.const_defined?(name)}
  .compact.each(&:delete_all)
dfaulken
źródło
1
Preferuj, selectgdy potrzebujesz użyć wyrażenia if wewnątrz bloku, w ten sposób unikniesz konieczności łączenia w łańcuch metody kompaktowej w celu usunięcia elementów zerowych.
Sebastian Palma,
4
BlogPost.find_each(&:destroy)
Philip
źródło
1
Jest to świetne rozwiązanie w przypadku małej ilości pamięci.
Epigene,
To jedyna odpowiedź, która bierze pod uwagę zużycie pamięci.
John
2
O mój Boże, po co robić pętlę ... bez sensu. po prostu usuń wszystkie rekordy DELETE FROM table, Model.delete_all
Imnl
@John, dlaczego jedno zapytanie zużywa więcej pamięci niż pętla zapytań?
Imnl
@Imnl Każda iteracja tworzy nową instancję danego modelu, aby mógł on przetwarzać wywołania zwrotne metody delete.
John
2

Jeśli Twój model nazywa się BlogPost, wyglądałoby to tak:

BlogPost.all.map(&:destroy)
stef
źródło
to pobierze każdy pojedynczy BlogPost i załaduje go do tablicy Ruby przed ich zniszczeniem.
hdgarrood
Zależy od ORM. Datamapper nie zrobiłby tego, ponieważ nie żądasz niczego na temat każdego modelu. A oto ślad stosu Mongoida, który pokazuje, że nie wybiera żadnych pól przed zniszczeniem każdego wpisu:MOPED: 127.0.0.1:27017 QUERY database=a_database collection=nothings selector={} flags=[:slave_ok] limit=0 skip=0 batch_size=nil fields=nil (0.3378ms)
stef
4
ponieważ jest to kwestia szyny, a pytający nie powiedział który ORM on używa, powinniśmy zakładać ActiveRecord
hdgarrood
2

Nowsza odpowiedź w przypadku, gdy chcesz usunąć wszystkie wpisy we wszystkich tabelach:

def reset
    Rails.application.eager_load!
    ActiveRecord::Base.descendants.each { |c| c.delete_all unless c == ActiveRecord::SchemaMigration  }
end

Więcej informacji na temat eager_load tutaj .

Po jej wywołaniu możemy uzyskać dostęp do wszystkich potomków ActiveRecord::Basei możemy zastosować a delete_allna wszystkich modelach.

Pamiętaj, że nie usuwamy tabeli SchemaMigration.

Simon Ninon
źródło