طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 121 · مبادئ قواعد البيانات
الدرس 21 · الوحدة 9: حذف البيانات

حذف البيانات بأمان: DELETE

الحذف لا رجعة فيه؛ نتعلم كيف نحذف بدقة وأمان، ومتى لا نحذف. ⏱ نحو 25 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تحذف صفوفًا محددة بـ DELETE … WHERE.
  • تتبع خطوات الحذف الآمن بالمعاملة.
  • تحذف مع احترام المفاتيح الأجنبية (الأبناء قبل الآباء).
  • تفرّق بين DELETE و TRUNCATE و DROP، وتطبّق الحذف الناعم.

١حذف الصفوف: DELETE

DELETE FROM يحذف الصفوف التي تحقق شرط WHERE. لا أعمدة في الأمر؛ لأنه يحذف الصف كاملًا:

query.sql
DELETE FROM productsWHERE id = 4; SELECT COUNT(*) AS products FROM products;
✓ حُذف صف واحد
النتيجة · صف واحد
products
11
query.sql
-- حذف كل المنتجات التي نفدت ولم تُطلب قطDELETE FROM productsWHERE stock = 0  AND id NOT IN (SELECT product_id FROM order_items); SELECT id, name, stock FROM products WHERE stock = 0;
النتيجة · لا صفوف
idnamestock
(لا توجد صفوف تحقق الشرط)

٢القاعدة الأهم: WHERE

query.sql
DELETE FROM order_items;   -- بلا WHERE! SELECT COUNT(*) AS items_left FROM order_items;
✓ حُذف 23 صفًّا
النتيجة · صف واحد
items_left
0

حُذفت كل أصناف كل الطلبات. لا سلة محذوفات ولا «تراجع» بعد الاعتماد.

query.sql
BEGIN;DELETE FROM customers WHERE city = 'جدة' AND id NOT IN (SELECT customer_id FROM orders);-- حُذف صف واحد كما توقعنا؟ نعتمدCOMMIT; SELECT name, city FROM customers WHERE city = 'جدة';
النتيجة · صف واحد
namecity
ريم الشهريجدة

٣الحذف والمفاتيح الأجنبية

لا يُحذف صف له أبناء يشيرون إليه، إلا إن كان المفتاح الأجنبي ON DELETE CASCADE. في «متجر الواحة» لا CASCADE، فلحذف طلب نحذف أصنافه أولًا:

query.sql
DELETE FROM orders WHERE id = 5;
✗ خطأ (السطر 1): مخالفة المفتاح الأجنبي: القيمة غير موجودة في الجدول الأصل، أو أن صفوفًا أخرى تعتمد على هذا الصف
query.sql
BEGIN;DELETE FROM order_items WHERE order_id = 5;   -- الأبناء أولًاDELETE FROM orders      WHERE id = 5;         -- ثم الأبCOMMIT; SELECT COUNT(*) AS orders FROM orders;
النتيجة · صف واحد
orders
11

٤الحذف الناعم: لا تحذف، بل علِّم

في أغلب الأنظمة الحقيقية لا تُحذف البيانات المهمة فعلًا؛ لأننا نحتاجها للتقارير والمراجعة والقانون. بل نضع علامة أنها «محذوفة» ونخفيها من الشاشات. ويسمى هذا الحذف الناعم Soft Delete:

query.sql
ALTER TABLE customers ADD COLUMN deleted_at TEXT;   -- فارغ = نشط -- «حذف» العميلة لمىUPDATE customers SET deleted_at = '2025-06-10' WHERE id = 10; -- الشاشات تعرض النشطين فقطSELECT id, name FROM customers WHERE deleted_at IS NULL;
النتيجة · 9 صفوف
idname
1سعود العتيبي
2نورة القحطاني
3خالد الحربي
4ريم الشهري
5فهد الدوسري
6سارة المطيري
7عبدالله الزهراني
8هند السبيعي
9ماجد الغامدي
الحذف الفعليالحذف الناعم
الاسترجاعمن النسخة الاحتياطية فقطبتعديل واحد: deleted_at = NULL
التقارير القديمةتتغير أو تنكسرسليمة
الثمن—كل استعلام يحتاج الشرط WHERE deleted_at IS NULL
متى؟بيانات مؤقتة، أو طلب قانوني بحذف بيانات شخصالعملاء والطلبات والفواتير

٥DELETE و TRUNCATE و DROP

الأمرماذا يحذف؟WHERE؟العائلة
DELETE FROM t WHERE …صفوفًا محددةنعمDML
DELETE FROM tكل الصفوف، ويبقى الجدوللاDML
TRUNCATE TABLE tكل الصفوف بسرعة، ويعيد الترقيم من 1 (MySQL)لاDDL
DROP TABLE tالجدول نفسه ببنيته وبياناتهلاDDL

TRUNCATE غير موجود في SQLite؛ مقابله DELETE FROM t;. وفي MySQL لا يعمل TRUNCATE على جدول تشير إليه مفاتيح أجنبية.

توقّع وتحقّق

حذف صفوف محددة:

DML.

حذف الجدول نفسه:

بنيته وبياناته.

الحذف الناعم يعني:

Soft Delete.

لحذف طلب بلا CASCADE:

الأبناء أولًا.

الخلاصة

تحدٍّ برمجي: تنظيف الطلبات الملغاة

متوسط

الإدارة قررت حذف الطلبات الملغاة نهائيًّا مع أصنافها، داخل معاملة.

المطلوب:
  • ابدأ معاملة.
  • احذف أصناف كل الطلبات الملغاة من order_items.
  • ثم احذف الطلبات الملغاة من orders.
  • اعتمد المعاملة. لا تحذف أي شيء آخر.
👀 اعرض النتيجة المطلوبة
بعد التنفيذ: SELECT COUNT(*) FROM orders WHERE status = 'ملغى'
COUNT(*)
0
بعد التنفيذ: SELECT id FROM orders ORDER BY id
id
1
2
3
4
6
7
8
9
10
11
12
بعد التنفيذ: SELECT order_id, product_id FROM order_items ORDER BY order_id, product_id
order_idproduct_id
11
13
22
25
37
38
39
43
61
66
611
72
710
83
85
91
109
1011
111
117
118
126
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء
  • لا طلبات ملغاة
  • بقية الطلبات سليمة
  • بقية الأصناف سليمة
  • داخل معاملة معتمدة

💡 تلميح 1
الأصناف: WHERE order_id IN (SELECT id FROM orders WHERE status = 'ملغى')
💡 تلميح 2
الترتيب: الأصناف ثم الطلبات.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

solution.sql
BEGIN; DELETE FROM order_itemsWHERE order_id IN (SELECT id FROM orders WHERE status = 'ملغى'); DELETE FROM ordersWHERE status = 'ملغى'; COMMIT;
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس