Jak usunąć wszystkie wiersze w tabeli za pomocą Eloquent?

145

Przypuszczałem, że użyję następującej składni:

MyModel::all()->delete();

Ale to nie zadziałało. Jestem pewien, że to super proste, ale szukałem dokumentacji na ten temat i nie mogę jej znaleźć!

Pete
źródło

Odpowiedzi:

296

Przyczyna MyModel::all()->delete()nie działa, ponieważ w all()rzeczywistości odpala zapytanie i zwraca kolekcję obiektów elokwentnych.

Możesz skorzystać z metody obcięcia, która działa dla Laravel 4 i 5:

MyModel::truncate();

Spowoduje to usunięcie wszystkich wierszy z tabeli bez rejestrowania usunięcia pojedynczych wierszy.

bilalq
źródło
1
Dodałem rozwiązanie Laravel 3 do mojego pytania, dla przyszłych czytelników.
Pete
40
Ładny. Działa to również na Laravel 5, jeśli ktoś inny
szukałby
14
Uwaga: truncate () resetuje również każdy licznik AUTO_INCREMENT (pamiętaj również, że nie możesz obcinać tabel, które mają ograniczenia klucza obcego).
William Turrell
10
FYI: Turncate nie spowoduje usunięcia wydarzeń.
Fusion
1
Jeśli naprawdę chcesz skorzystać MyModel::all()->delete(), użyjforeach (MyModel::all() as $e) { $e->delete() }
Ema4rl
75

Rozwiązanie Laravel 5.2+ .

Model::getQuery()->delete();

Po prostu weź bazowy kreator z nazwą tabeli i zrób cokolwiek. Nie może być bardziej uporządkowany.

Laravel 5,6 rozwiązanie

\App\Model::query()->delete();
Yauheni Prakopchyk
źródło
9
Na wypadek, gdyby ktokolwiek był zdezorientowany, dlaczego to działa, klasa Model przekazuje metody do Builder za pośrednictwem magicznej metody __call tutaj . Ponieważ sama klasa modelu ma metodę delete, wywołanie Model :: delete () wywołuje metodę Model, gdy naprawdę potrzebujesz metody Builder. Aby jawnie pobrać kreator, możesz użyć metody getQuery ().
kevinAlbs,
To również nie usuwa powiązanych tabel, jeśli chcesz.
Terje Nesthus,
Wymusi
Model :: whereNotNull ('id') -> delete (); - wykona miękkie usuwanie, gdy miękkie usuwanie jest włączone
shalini
64

Możesz użyć, Model::truncate()jeśli wyłączysz foreign_key_checks(zakładam, że używasz MySQL).

DB::statement("SET foreign_key_checks=0");
Model::truncate();
DB::statement("SET foreign_key_checks=1");
Fortex
źródło
2
W Laravel 4 używasz DB ::
unprepared
możesz także użyć Schema :: disableForeignKeyConstraints (); & Schemat :: enableForeignKeyConstraints ();
Eleazar Resendez
34

Widziałem obie metody używane w plikach seed.

// Uncomment the below to wipe the table clean before populating

DB::table('table_name')->truncate();

//or

DB::table('table_name')->delete();

Nawet jeśli nie możesz użyć pierwszego, jeśli chcesz ustawić klucze obce .

Nie można obciąć tabeli, do której odwołuje się ograniczenie klucza obcego

Więc dobrym pomysłem może być skorzystanie z drugiego.

giannis christofakis
źródło
2
deleteoczywiście to nie to samo, co truncatejednak.
Joel Mellon
2
@sudopeople Bardzo pomocne byłoby wskazanie różnicy. Mógłbym również dodać to do mojej odpowiedzi .
giannis christofakis
4
Nie można użyć TRUNCATE w transakcji, ponieważ ROLLBACK nie ma na nią wpływu. W takim przypadku można to osiągnąć za pomocą (new MyModel) -> newQuery () -> delete ().
hammurabi
12

Istnieje sposób pośredni:

myModel:where('anyColumnName', 'like', '%%')->delete();

Przykład:

User:where('id', 'like' '%%')->delete();

Informacje o narzędziu do tworzenia zapytań Laravel: https://laravel.com/docs/5.4/queries

Rejaul
źródło
1
@aschipfl właściwie niewiele do wyjaśnienia. Kod uruchamia SQL, DELETE FROM users WHERE id LIKE '%%'który dopasowuje wszystkie wiersze w tabeli, usuwając w ten sposób wszystko.
Hkan
To mnie wciągnęło. Skończyło się na tym, że wykonałem pluck () na innym modelu, aby uzyskać tablicę identyfikatorów, których potrzebowałem, a następnie użyłem tej tablicy do usunięcia wszystkich rekordów z mojego modelu za pomocą whereInmetody: $itemsAllContentIDs = Item::where('user_id', $userId)->pluck('item_content_id')->all(); ItemsContent::whereIn('id', $itemsAllContentIDs)->delete();
Keith DC
10

Chciałem dodać kolejną opcję dla tych, którzy dostają się do tego wątku przez Google. Musiałem to zrobić, ale chciałem zachować moją wartość automatycznego zwiększania, która jest truncate()resetowana. Nie chciałem też DB::niczego używać , ponieważ chciałem działać bezpośrednio na obiekcie modelu. Więc poszedłem z tym:

Model::whereNotNull('id')->delete();

Oczywiście kolumna będzie musiała faktycznie istnieć, ale w standardowym, nieszablonowym modelu elokwentnym idkolumna istnieje i nigdy nie jest pusta. Nie wiem, czy to najlepszy wybór, ale działa na moje potrzeby.

lookitsatravis
źródło
Model::delete();osiągnie to samo.
Leng
5
Niestety Model::delete()rzuca wyjątek Non-static method Illuminate\Database\Eloquent\Model::delete() should not be called statically, przynajmniej w Laravel 5.0.
Dave James Miller,
6

Nie mogłem użyć, Model::truncate()ponieważ spowodowałoby to błąd:

SQLSTATE [42000]: Błąd składni lub naruszenie zasad dostępu: 1701 Nie można obciąć tabeli, do której odwołuje się ograniczenie klucza obcego

I niestety Model::delete()nie działa (przynajmniej w Laravel 5.0):

Metoda niestatyczna Illuminate \ Database \ Eloquent \ Model :: delete () nie powinna być wywoływana statycznie, zakładając $ this z niezgodnego kontekstu

Ale to działa:

(new Model)->newQuery()->delete()

Spowoduje to nietrwałe usunięcie wszystkich wierszy, jeśli skonfigurowano usuwanie nietrwałe. Aby całkowicie usunąć wszystkie wiersze, w tym usunięte nietrwale, możesz zmienić to:

(new Model)->newQueryWithoutScopes()->forceDelete()
Dave James Miller
źródło
4

Wydaje się, że najlepszym sposobem wykonania tej operacji w programie Laravel 3jest użycie Fluentinterfejsu do obcięcia tabeli, jak pokazano poniżej

DB::query("TRUNCATE TABLE mytable");
Pete
źródło
2

Możesz wypróbować tę jedną linijkę, która zachowuje również miękkie usuwanie:

Model::whereRaw('1=1')->delete();
jfeid
źródło
1

proste rozwiązanie:

 Mymodel::query()->delete();
ali filali
źródło
0

Podobnie jak w przypadku odpowiedzi Travisa Vignona, zażądałem danych z wymownego modelu i jeśli warunki były prawidłowe, musiałem albo usunąć, albo zaktualizować model. Skończyło się na tym, że otrzymałem minimalne i maksymalne pole zwrócone przez moje zapytanie (na wypadek, gdyby do tabeli dodano inne pole, które spełniałoby moje kryteria wyboru) wraz z pierwotnymi kryteriami wyboru, aby zaktualizować pola za pomocą jednego surowego zapytania SQL (jak w przeciwieństwie do jednego wymownego zapytania na obiekt w kolekcji).

Wiem, że użycie surowego SQL narusza filozofię pięknego kodu Laravels, ale trudno byłoby znieść setki zapytań zamiast jednego.

Sidney
źródło
0

Może zrobić pętla też ...

$collection = Model::get();

foreach($collection as $c) {

$c->delete();

}
Sam Solomon
źródło
Technicznie tak ... ale IMO wydaje się trochę niepotrzebne, ponieważ istnieją lepsze opcje pojedynczego zapytania.
Pete
@Pete, wiem ... inni już udzielili odpowiedzi ... próbowałem odpowiedzieć na inną możliwą metodę ...
Sam Solomon
1
To faktycznie działa dla mnie, ponieważ planuję archiwizować Modele w kolekcji na podstawie określonych reguł, ale także usuwać je z tej codziennie aktywnej tabeli.
James Perih,
-2

Rozwiązanie współpracujące z Lumenem 5.5 z ograniczeniami kluczy obcych:

$categories = MusicCategory::all();
foreach($categories as $category)
{
$category->delete();

}
return response()->json(['error' => false]);
Alain Berrier
źródło