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

تعديل النموذج: ALTER TABLE

نطوّر بنية الجداول بلا خسارة بيانات، ونوازن بين التطبيع والسرعة. ⏱ نحو 25 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تضيف الأعمدة وتعيد تسميتها وتحذفها بـ ALTER TABLE.
  • تتعامل مع القيم الافتراضية للأعمدة الجديدة.
  • تعرف أوامر MySQL الإضافية مثل MODIFY COLUMN و ADD CONSTRAINT.
  • تقيّم قرار عكس التطبيع بين المكسب والثمن.

١النموذج يتغير مع الوقت

بعد أشهر من تشغيل المتجر، طلبت الإدارة: «نريد بريد العميل»، و«سمّوا عمود المخزون باسم أوضح». لا نحذف الجدول ونعيد إنشاءه (فنخسر البيانات)؛ بل نعدّل بنيته بالأمر ALTER TABLE، وبياناته باقية:

العمليةالأمر
إضافة عمودALTER TABLE t ADD COLUMN c TYPE;
إعادة تسمية عمودALTER TABLE t RENAME COLUMN old TO new;
حذف عمودALTER TABLE t DROP COLUMN c;
إعادة تسمية جدولALTER TABLE t RENAME TO new_name;

٢إضافة عمود

query.sql
ALTER TABLE customers ADD COLUMN email TEXT; SELECT id, name, email FROM customers WHERE id <= 3;
النتيجة · 3 صفوف
idnameemail
1سعود العتيبيNULL
2نورة القحطانيNULL
3خالد الحربيNULL

العمود الجديد فارغ (NULL) في الصفوف القديمة، حتى نملأه.

ويمكن أن نعطيه قيمة افتراضية تُملأ بها الصفوف القديمة والجديدة:

query.sql
ALTER TABLE products ADD COLUMN discount INTEGER DEFAULT 0; SELECT name, price, discount FROM products WHERE id <= 3;
النتيجة · 3 صفوف
namepricediscount
قهوة عربية 250غ350
شاي أخضر180
تمر عجوة 1كغ900

٣إعادة التسمية والحذف

query.sql
ALTER TABLE products RENAME COLUMN stock TO quantity;ALTER TABLE customers DROP COLUMN joined; SELECT name, quantity FROM products WHERE id = 1;SELECT * FROM customers WHERE id = 1;
✓ عُدِّل الجدول
✓ عُدِّل الجدول
النتيجة · صف واحد
namequantity
قهوة عربية 250غ40
النتيجة · صف واحد
idnamecityphone
1سعود العتيبيالمدينة المنورة0551000001

حذف العمود يحذف بياناته نهائيًّا. وقبل إعادة تسمية عمود، ابحث عن كل استعلام وتطبيق يستخدم الاسم القديم؛ لأنها ستتعطل.

query.sql
ALTER TABLE products DROP COLUMN id;
✗ خطأ (السطر 1): لا يمكن حذف عمود المفتاح الأساسي id

لا يُحذف عمود المفتاح الأساسي، ولا عمود تعتمد عليه مفاتيح أجنبية أو فهارس، قبل إزالة ما يعتمد عليه.

٤في MySQL أكثر

SQLite يدعم العمليات الأربع السابقة فقط. أما MySQL فيسمح أيضًا بتغيير نوع العمود وإضافة القيود لاحقًا:

mysql.sql
-- تغيير نوع العمود أو قيودهALTER TABLE products MODIFY COLUMN price DECIMAL(10,2) NOT NULL; -- إضافة قيد CHECK ومفتاح أجنبي بعد الإنشاءALTER TABLE products ADD CONSTRAINT chk_price CHECK (price > 0);ALTER TABLE orders ADD CONSTRAINT fk_customer  FOREIGN KEY (customer_id) REFERENCES customers(id); -- حذف قيدALTER TABLE products DROP CHECK chk_price;

٥تحسين النموذج: التوازن بين التطبيع والأداء

تحليل النموذج لا ينتهي بالتطبيع. نراقب الاستعلامات الأكثر استخدامًا، ونسأل: هل يجعلها التصميم بطيئة؟ مثال: صفحة «طلباتي» تعرض إجمالي كل طلب، فتحسبه في كل مرة من جدول الأصناف:

query.sql
SELECT order_id, SUM(qty * price) AS totalFROM order_itemsGROUP BY order_idLIMIT 5;
النتيجة · 5 صفوف
order_idtotal
1160
2204
3171
4180
5120

مع ملايين الأصناف قد يصير هذا الحساب بطيئًا. فيقرر المصمم عكس التطبيع: يضيف عمودًا total إلى جدول الطلبات، ويحسبه مرة واحدة:

query.sql
ALTER TABLE orders ADD COLUMN total REAL; UPDATE orders SET total = (  SELECT SUM(qty * price) FROM order_items WHERE order_id = orders.id); SELECT id, order_date, total FROM orders LIMIT 5;
النتيجة · 5 صفوف
idorder_datetotal
12025-01-10160
22025-01-12204
32025-02-05171
42025-02-18180
52025-03-02120
المكسبالثمن
عمود total المكررقراءة الإجمالي فورية بلا حساب.يجب تحديثه مع كل تعديل في الأصناف، وإلا صار خاطئًا (شذوذ تحديث!).

قاعدة: طبّع أولًا، ثم اعكس التطبيع فقط حين تقيس بطئًا حقيقيًّا، وبوعي بالثمن. وفي الوحدتين 10 و 11 ستتعلم أدوات القياس: زمن التنفيذ وخطة التنفيذ.

توقّع وتحقّق

إضافة عمود إلى جدول موجود:

DDL.

قيمة العمود الجديد في الصفوف القديمة بلا DEFAULT:

لا قيمة.

تغيير نوع العمود في MySQL:

MySQL.

عكس التطبيع يُقرَّر بعد:

بوعي.

الخلاصة

تحدٍّ برمجي: طلبات الإدارة

متوسط

نفّذ تعديلات الإدارة على «متجر الواحة» دون فقد أي بيانات.

المطلوب:
  • أضف إلى customers عمود البريد email نصيًّا.
  • أضف إلى products عمود is_active عددًا صحيحًا افتراضيًّا 1.
  • أعد تسمية عمود status في orders إلى order_status.
👀 اعرض النتيجة المطلوبة
بعد التنفيذ: SELECT name FROM pragma_table_info('customers') ORDER BY cid
name
id
name
city
phone
joined
email
بعد التنفيذ: SELECT id, is_active FROM products
idis_active
11
21
31
41
51
61
71
81
91
101
111
121
بعد التنفيذ: SELECT name FROM pragma_table_info('orders') ORDER BY cid
name
id
customer_id
order_date
order_status
بعد التنفيذ: SELECT id, order_status FROM orders
idorder_status
1مُسلَّم
2مُسلَّم
3مُسلَّم
4مُسلَّم
5ملغى
6مُسلَّم
7قيد الشحن
8قيد الشحن
9جديد
10جديد
11جديد
12جديد
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء
  • أعمدة customers صحيحة
  • كل المنتجات القديمة صارت نشطة (1)
  • أعمدة orders صحيحة
  • لم تُفقد أي طلبات

💡 تلميح 1
ثلاثة أوامر ALTER TABLE، كل أمر لتعديل واحد.
💡 تلميح 2
ADD COLUMN is_active INTEGER DEFAULT 1

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

solution.sql
ALTER TABLE customers ADD COLUMN email TEXT;ALTER TABLE products ADD COLUMN is_active INTEGER DEFAULT 1;ALTER TABLE orders RENAME COLUMN status TO order_status;
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

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