Как удалить все строки в таблице с помощью Eloquent?

135

Я предполагал использовать следующий синтаксис:

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

Но это не сработало. Я уверен, что это очень просто, но я искал документацию по этой теме и не нашел!

Пит
источник

Ответы:

279

Причина MyModel::all()->delete()неработоспособности заключается в том, что на all()самом деле запрос запускается и возвращает коллекцию объектов Eloquent.

Вы можете использовать метод truncate, это работает для Laravel 4 и 5:

MyModel::truncate();

Это удаляет все строки из таблицы без регистрации удаления отдельных строк.

bilalq
источник
1
Я добавил на свой вопрос решение Laravel 3 для будущих читателей.
Pete
39
Ницца. Это работает и на Laravel 5, если в 2016 году кто-нибудь еще
погуглиет.
14
Примечание: truncate () также сбрасывает любой счетчик AUTO_INCREMENT (также обратите внимание, что вы не можете усекать таблицы с ограничениями внешнего ключа.)
Уильям Туррелл,
10
К вашему сведению: Turncate не будет запускать события удаления.
Fusion
1
Если действительно хотите использовать MyModel::all()->delete(), используйтеforeach (MyModel::all() as $e) { $e->delete() }
Ema4rl 02
70

Решение Laravel 5.2+ .

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

Просто возьмите базовый конструктор с именем таблицы и сделайте что угодно. Не может быть лучше этого.

Решение Laravel 5.6

\App\Model::query()->delete();
Евгений Пракопчик
источник
9
В случае , если кто - то был смущен о том, почему это работает, модель перенаправляет класса методы к Builder с помощью метода волшебной __call здесь . Поскольку сам класс модели имеет метод удаления, вызов Model :: delete () вызывает метод Model, когда вам действительно нужен метод Builder. Итак, чтобы получить конструктор явно, вы можете использовать getQuery ().
kevinAlbs 07
Это также не удаляет связанные таблицы, если вы этого хотите.
Terje Nesthus
Это приведет к принудительному удалению всех записей, независимо от того,
включено
Модель :: whereNotNull ( 'ID') -> Удалить (); - будет выполнять мягкое удаление, когда мягкое удаление включено
shalini
62

Вы можете использовать, Model::truncate()если отключите foreign_key_checks(я предполагаю, что вы используете MySQL).

DB::statement("SET foreign_key_checks=0");
Model::truncate();
DB::statement("SET foreign_key_checks=1");
Fortex
источник
2
В Laravel 4 вы используете DB ::
unprepared
вы также можете использовать Schema :: disableForeignKeyConstraints (); & Схема :: enableForeignKeyConstraints ();
Eleazar
33

Я видел, что оба метода использовались в исходных файлах.

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

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

//or

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

Даже если вы не можете использовать первый, если хотите установить внешние ключи .

Невозможно усечь таблицу, указанную в ограничении внешнего ключа

Так что было бы неплохо использовать второй.

Яннис Кристофакис
источник
2
deleteочевидно, это не то же самое truncate.
Джоэл Меллон
2
@sudopeople Было бы очень полезно указать на разницу. Я мог бы также добавить это к своему ответу .
Яннис Кристофакис
4
TRUNCATE нельзя использовать в транзакции, поскольку на него не влияет ROLLBACK. В этом случае это может быть достигнуто с помощью (new MyModel) -> newQuery () -> delete ().
Хаммурапи
12

Есть косвенный способ:

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

Пример:

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

Информация о построителе запросов Laravel: https://laravel.com/docs/5.4/queries

Rejaul
источник
1
@aschipfl на самом деле особо нечего объяснять. Код запускает SQL, DELETE FROM users WHERE id LIKE '%%'который соответствует всем строкам в таблице, тем самым удаляя все.
Hkan
Это поставило меня в путь. В итоге я выполнил pluck () на другой модели, чтобы получить массив необходимых мне идентификаторов, а затем использовал этот массив для удаления всех записей из моей модели с помощью следующего whereInметода: $itemsAllContentIDs = Item::where('user_id', $userId)->pluck('item_content_id')->all(); ItemsContent::whereIn('id', $itemsAllContentIDs)->delete();
Кейт
9

Я хотел добавить еще один вариант для тех, кто попадает в эту ветку через Google. Мне нужно было это сделать, но я хотел сохранить значение автоинкремента, которое truncate()сбрасывается. Я также не хотел DB::ничего использовать, потому что хотел работать непосредственно с объектом модели. Итак, я пошел с этим:

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

Очевидно, что столбец должен действительно существовать, но в стандартной готовой модели Eloquent idстолбец существует и никогда не имеет значения NULL. Не знаю, лучший ли это выбор, но он работает для моих целей.

lookitsatravis
источник
Model::delete();выполнит то же самое.
Ленг
5
К сожалению, Model::delete()выдает исключение Non-static method Illuminate\Database\Eloquent\Model::delete() should not be called statically, по крайней мере, в Laravel 5.0.
Дэйв Джеймс Миллер
6

Я не смог использовать, так Model::truncate()как это вызвало бы ошибку:

SQLSTATE [42000]: синтаксическая ошибка или нарушение прав доступа: 1701 Невозможно усечь таблицу, на которую имеется ссылка в ограничении внешнего ключа

И, к сожалению Model::delete(), не работает (по крайней мере, в Laravel 5.0):

Нестатический метод Illuminate \ Database \ Eloquent \ Model :: delete () не должен вызываться статически, если $ this из несовместимого контекста

Но это действительно работает:

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

Это приведет к мягкому удалению всех строк, если у вас настроено мягкое удаление. Чтобы полностью удалить все строки, включая частично удаленные, вы можете изменить это:

(new Model)->newQueryWithoutScopes()->forceDelete()
Дэйв Джеймс Миллер
источник
4

Лучшим способом выполнения этой операции, по- Laravel 3видимому, является использование Fluentинтерфейса для усечения таблицы, как показано ниже.

DB::query("TRUNCATE TABLE mytable");
Пит
источник
2

Вы можете попробовать этот однострочник, который также сохраняет мягкие удаления:

Model::whereRaw('1=1')->delete();
jfeid
источник
1

простое решение:

 Mymodel::query()->delete();
Али Филали
источник
0

Подобно ответу Трэвиса Виньона, мне потребовались данные из красноречивой модели, и если условия были правильными, мне нужно было либо удалить, либо обновить модель. Я получил минимальное и максимальное значение поля, возвращаемое моим запросом (в случае, если в таблицу было добавлено другое поле, которое соответствовало бы моим критериям выбора) вместе с исходными критериями выбора для обновления полей с помощью одного необработанного SQL-запроса (как в отличие от одного красноречивого запроса на объект в коллекции).

Я знаю, что использование необработанного SQL нарушает философию прекрасного кода Laravel, но было бы трудно переварить, возможно, сотни запросов вместо одного.

Сидней
источник
0

Может сделать петля тоже ..

$collection = Model::get();

foreach($collection as $c) {

$c->delete();

}
Сэм Соломон
источник
Технически да ... но ИМО это кажется немного ненужным, поскольку есть лучшие варианты одиночного запроса.
Пит
@Pete, я знаю ... другие уже дали свои ответы ... я пытался ответить другим возможным способом ...
Сэм Соломон,
1
Это действительно работает для меня, так как я планирую архивировать модели в коллекции на основе определенных правил, но также очищать их из этой ежедневной активной таблицы.
Джеймс Перих 06
-1

Решение, которое работает с Lumen 5.5 с ограничениями внешних ключей:

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

}
return response()->json(['error' => false]);
Ален Берье
источник