จะลบแถวทั้งหมดในตารางโดยใช้ Eloquent ได้อย่างไร?


145

ฉันเดาว่าจะใช้ไวยากรณ์ต่อไปนี้:

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

แต่นั่นไม่ได้ผล ฉันแน่ใจว่ามันง่ายสุด ๆ แต่ฉันค้นหาเอกสารเกี่ยวกับเรื่องแล้วไม่พบ!

คำตอบ:


296

สาเหตุที่MyModel::all()->delete()ไม่ได้ผลเป็นเพราะall()จริงๆแล้วการเริ่มการค้นหาและส่งคืนชุดของวัตถุที่มีคุณภาพ

คุณสามารถใช้วิธีการตัดทอนซึ่งใช้ได้กับ Laravel 4 และ 5:

MyModel::truncate();

ซึ่งจะลดแถวทั้งหมดออกจากตารางโดยไม่ต้องบันทึกการลบแต่ละแถว


1
ฉันได้เพิ่มวิธีแก้ปัญหา Laravel 3 ในคำถามของฉันสำหรับผู้อ่านในอนาคต
พีท

40
ดี. สิ่งนี้ใช้ได้กับ Laravel 5 เช่นกันหากมีใคร Googles ตัวเองที่นี่ในปี 2559
samiles

14
หมายเหตุ: truncate () ยังรีเซ็ตตัวนับ AUTO_INCREMENT ใด ๆ (โปรดทราบว่าคุณไม่สามารถตัดทอนตารางที่มีข้อ จำกัด ของคีย์ต่างประเทศได้)
William Turrell

10
FYI: Turncate จะไม่ทริกเกอร์เหตุการณ์การลบ
Fusion

1
หากต้องการใช้จริงๆให้MyModel::all()->delete()ใช้foreach (MyModel::all() as $e) { $e->delete() }
Ema4rl

75

โซลูชันLaravel 5.2+

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

เพียงแค่คว้าตัวสร้างพื้นฐานที่มีชื่อตารางแล้วทำอะไรก็ได้ ไม่สามารถเป็นระเบียบมากไปกว่านั้น

โซลูชันLaravel 5.6

\App\Model::query()->delete();

9
ในกรณีที่คนอื่นสับสนเกี่ยวกับสาเหตุที่งานนี้วิธีการส่งต่อรูปแบบการเรียนที่จะสร้างผ่านทางวิธี __call มายากลที่นี่ เนื่องจากคลาสโมเดลเองมีเมธอดลบการเรียก Model :: delete () จึงเรียก Model method เมื่อคุณต้องการเมธอด Builder จริงๆ ดังนั้นเพื่อให้ตัวสร้างชัดเจนคุณสามารถใช้ getQuery ()
kevinAlbs

นอกจากนี้ยังไม่ลบตารางที่เกี่ยวข้องหากคุณต้องการ
Terje Nesthus

จะบังคับให้ลบบันทึกทั้งหมดไม่ว่าจะเปิดหรือปิดการลบแบบซอฟต์
shalini

รุ่น :: whereNotNull ('id') -> ลบ (); - จะทำการลบแบบนุ่มนวลเมื่อเปิดซอฟต์ลบ
shalini

64

คุณสามารถใช้ได้Model::truncate()ถ้าคุณปิดการใช้งานforeign_key_checks(ฉันถือว่าคุณใช้ MySQL)

DB::statement("SET foreign_key_checks=0");
Model::truncate();
DB::statement("SET foreign_key_checks=1");

2
ใน Laravel 4 คุณใช้ DB :: ไม่ได้เตรียมตัว ()
swdev

คุณยังสามารถใช้ Schema :: disableForeignKeyConstraints (); & Schema :: enableForeignKeyConstraints ();
Eleazar Resendez

34

ฉันเคยเห็นทั้งสองวิธีที่ใช้ในไฟล์ seed

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

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

//or

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

ถึงแม้ว่าคุณจะไม่สามารถใช้เป็นคนแรกถ้าคุณต้องการตั้งค่าปุ่มต่างประเทศ

ไม่สามารถตัดทอนตารางที่อ้างอิงในข้อ จำกัด ของคีย์ต่างประเทศ

ดังนั้นจึงควรใช้อันที่สอง


2
deleteเห็นได้ชัดว่าไม่เหมือนกับที่truncateว่า
Joel Mellon

2
@sudopeople การชี้ความแตกต่างจะเป็นประโยชน์มาก ฉันยังสามารถเพิ่มคำตอบของฉันได้
giannis christofakis

4
ไม่สามารถใช้ TRUNCATE ในธุรกรรมได้เนื่องจากไม่ได้รับผลกระทบจาก ROLLBACK ในกรณีนี้สามารถทำได้ด้วย (MyModel ใหม่) -> newQuery () -> delete ()
hammurabi

12

มีวิธีทางอ้อม:

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

ตัวอย่าง:

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

ข้อมูลตัวสร้างแบบสอบถาม Laravel: https://laravel.com/docs/5.4/queries


1
@aschipfl ไม่มากที่จะอธิบายจริง รหัสเรียกใช้ SQL DELETE FROM users WHERE id LIKE '%%'ซึ่งตรงกับแถวทั้งหมดในตารางจึงลบทุกอย่าง
Hkan

สิ่งนี้ทำให้ฉันไปได้ ฉันลงเอยด้วยการถอน () ในโมเดลอื่นเพื่อรับอาร์เรย์ของ ID ที่ฉันต้องการจากนั้นใช้อาร์เรย์นั้นเพื่อลบเร็กคอร์ดทั้งหมดจากโมเดลของฉันโดยใช้whereInวิธีการ: $itemsAllContentIDs = Item::where('user_id', $userId)->pluck('item_content_id')->all(); ItemsContent::whereIn('id', $itemsAllContentIDs)->delete();
Keith DC

10

ฉันต้องการเพิ่มตัวเลือกอื่นสำหรับผู้ที่เข้ามาที่กระทู้นี้ผ่าน Google ฉันต้องการทำสิ่งนี้ให้สำเร็จ แต่ต้องการคงค่าที่เพิ่มขึ้นอัตโนมัติซึ่งจะtruncate()รีเซ็ต ฉันยังไม่ต้องการใช้DB::อะไรเลยเพราะฉันต้องการใช้งานจากวัตถุโมเดลโดยตรง ดังนั้นฉันไปกับสิ่งนี้:

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

เห็นได้ชัดว่าคอลัมน์จะต้องมีอยู่จริง แต่ในรูปแบบ Eloquent มาตรฐานที่ไม่idอยู่ในกรอบคอลัมน์นั้นจะมีอยู่และไม่เป็นค่าว่าง ฉันไม่รู้ว่านี่เป็นทางเลือกที่ดีที่สุดหรือเปล่า แต่มันใช้ได้กับจุดประสงค์ของฉัน


Model::delete();จะสำเร็จในสิ่งเดียวกัน
เล้ง

5
น่าเสียดายที่Model::delete()มีข้อยกเว้นNon-static method Illuminate\Database\Eloquent\Model::delete() should not be called staticallyอย่างน้อยใน Laravel 5.0
Dave James Miller

6

ฉันไม่สามารถใช้งานได้Model::truncate()เนื่องจากจะเกิดข้อผิดพลาด:

SQLSTATE [42000]: ข้อผิดพลาดทางไวยากรณ์หรือการละเมิดการเข้าถึง: 1701 ไม่สามารถตัดทอนตารางที่อ้างถึงในข้อ จำกัด ของคีย์ต่างประเทศ

และน่าเสียดายที่ใช้Model::delete()ไม่ได้ (อย่างน้อยใน Laravel 5.0):

ไม่ควรเรียกวิธีการแบบไม่คงที่ Illuminate \ Database \ Eloquent \ Model :: delete () แบบคงที่โดยสมมติว่า $ นี้มาจากบริบทที่เข้ากันไม่ได้

แต่มันใช้งานได้:

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

วิธีนี้จะลบแถวทั้งหมดอย่างนุ่มนวลหากคุณตั้งค่าการลบแบบนุ่มนวล หากต้องการลบแถวทั้งหมดอย่างสมบูรณ์รวมทั้งแถวที่ลบแบบอ่อนคุณสามารถเปลี่ยนเป็น:

(new Model)->newQueryWithoutScopes()->forceDelete()

4

วิธีที่ดีที่สุดในการดำเนินการนี้ให้สำเร็จLaravel 3ดูเหมือนจะเป็นการใช้Fluentอินเทอร์เฟซเพื่อตัดทอนตารางดังที่แสดงด้านล่าง

DB::query("TRUNCATE TABLE mytable");

2

คุณสามารถลองซับเดียวซึ่งรักษาการลบแบบซอฟต์ไว้ได้:

Model::whereRaw('1=1')->delete();


0

ในทำนองเดียวกันกับคำตอบของ Travis vignon ฉันต้องการข้อมูลจากแบบจำลองที่คมคายและหากเงื่อนไขถูกต้องฉันจำเป็นต้องลบหรืออัปเดตโมเดล ฉันได้รับฟิลด์ต่ำสุดและสูงสุดที่ฉันส่งคืนโดยแบบสอบถามของฉัน (ในกรณีที่มีการเพิ่มฟิลด์อื่นในตารางที่ตรงกับเกณฑ์การเลือกของฉัน) พร้อมกับเกณฑ์การเลือกดั้งเดิมเพื่ออัปเดตฟิลด์ผ่านแบบสอบถาม SQL ดิบหนึ่งรายการ (เช่น ตรงข้ามกับหนึ่งแบบสอบถามที่คมชัดต่อวัตถุในคอลเลกชัน)

ฉันรู้ว่าการใช้ SQL ดิบนั้นละเมิดปรัชญารหัสที่สวยงามของ laravels แต่มันก็ยากที่จะท้องได้อาจมีการสืบค้นหลายร้อยรายการแทน


0

สามารถทำได้ ห่วงเหมือนกัน ..

$collection = Model::get();

foreach($collection as $c) {

$c->delete();

}

ในทางเทคนิคใช่ ... แต่ IMO ที่ดูเหมือนไม่จำเป็นเล็กน้อยเนื่องจากมีตัวเลือกการสืบค้นเดี่ยวที่ดีกว่า
พีท

@Pete ฉันรู้ .. คนอื่นให้คำตอบไปแล้ว ... ฉันพยายามตอบวิธีอื่นที่เป็นไปได้ที่จะทำ ..
Sam Solomon

1
สิ่งนี้ใช้งานได้จริงสำหรับฉันเนื่องจากฉันวางแผนที่จะเก็บแบบจำลองในคอลเล็กชันตามกฎเฉพาะ แต่ยังล้างออกจากตารางที่ใช้งานประจำวันนั้นด้วย
James Perih

-2

โซลูชันที่ทำงานกับ Lumen 5.5 ที่มีข้อ จำกัด ของคีย์ต่างประเทศ:

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

}
return response()->json(['error' => false]);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.