تعديل النموذج: 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; |
٢إضافة عمود
ALTER TABLE customers ADD COLUMN email TEXT; SELECT id, name, email FROM customers WHERE id <= 3;
| id | name | |
|---|---|---|
| 1 | سعود العتيبي | NULL |
| 2 | نورة القحطاني | NULL |
| 3 | خالد الحربي | NULL |
العمود الجديد فارغ (NULL) في الصفوف القديمة، حتى نملأه.
ويمكن أن نعطيه قيمة افتراضية تُملأ بها الصفوف القديمة والجديدة:
ALTER TABLE products ADD COLUMN discount INTEGER DEFAULT 0; SELECT name, price, discount FROM products WHERE id <= 3;
| name | price | discount |
|---|---|---|
| قهوة عربية 250غ | 35 | 0 |
| شاي أخضر | 18 | 0 |
| تمر عجوة 1كغ | 90 | 0 |
٣إعادة التسمية والحذف
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;
| name | quantity |
|---|---|
| قهوة عربية 250غ | 40 |
| id | name | city | phone |
|---|---|---|---|
| 1 | سعود العتيبي | المدينة المنورة | 0551000001 |
حذف العمود يحذف بياناته نهائيًّا. وقبل إعادة تسمية عمود، ابحث عن كل استعلام وتطبيق يستخدم الاسم القديم؛ لأنها ستتعطل.
ALTER TABLE products DROP COLUMN id;لا يُحذف عمود المفتاح الأساسي، ولا عمود تعتمد عليه مفاتيح أجنبية أو فهارس، قبل إزالة ما يعتمد عليه.
٤في MySQL أكثر
SQLite يدعم العمليات الأربع السابقة فقط. أما MySQL فيسمح أيضًا بتغيير نوع العمود وإضافة القيود لاحقًا:
-- تغيير نوع العمود أو قيوده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;
٥تحسين النموذج: التوازن بين التطبيع والأداء
تحليل النموذج لا ينتهي بالتطبيع. نراقب الاستعلامات الأكثر استخدامًا، ونسأل: هل يجعلها التصميم بطيئة؟ مثال: صفحة «طلباتي» تعرض إجمالي كل طلب، فتحسبه في كل مرة من جدول الأصناف:
SELECT order_id, SUM(qty * price) AS totalFROM order_itemsGROUP BY order_idLIMIT 5;
| order_id | total |
|---|---|
| 1 | 160 |
| 2 | 204 |
| 3 | 171 |
| 4 | 180 |
| 5 | 120 |
مع ملايين الأصناف قد يصير هذا الحساب بطيئًا. فيقرر المصمم عكس التطبيع: يضيف عمودًا total إلى جدول الطلبات، ويحسبه مرة واحدة:
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;
| id | order_date | total |
|---|---|---|
| 1 | 2025-01-10 | 160 |
| 2 | 2025-01-12 | 204 |
| 3 | 2025-02-05 | 171 |
| 4 | 2025-02-18 | 180 |
| 5 | 2025-03-02 | 120 |
| المكسب | الثمن | |
|---|---|---|
| عمود total المكرر | قراءة الإجمالي فورية بلا حساب. | يجب تحديثه مع كل تعديل في الأصناف، وإلا صار خاطئًا (شذوذ تحديث!). |
قاعدة: طبّع أولًا، ثم اعكس التطبيع فقط حين تقيس بطئًا حقيقيًّا، وبوعي بالثمن. وفي الوحدتين 10 و 11 ستتعلم أدوات القياس: زمن التنفيذ وخطة التنفيذ.
توقّع وتحقّق
إضافة عمود إلى جدول موجود:
DDL.قيمة العمود الجديد في الصفوف القديمة بلا DEFAULT:
تغيير نوع العمود في MySQL:
MySQL.عكس التطبيع يُقرَّر بعد:
الخلاصة
ALTER TABLEيعدّل بنية الجدول وتبقى بياناته.ADD COLUMNوRENAME COLUMNوDROP COLUMNوRENAME TO.MySQLيضيفMODIFY COLUMNوADD CONSTRAINT.- عكس التطبيع: تكرار مقصود للسرعة، ثمنه صعوبة إبقاء النسخ متطابقة.
تحدٍّ برمجي: طلبات الإدارة
متوسطنفّذ تعديلات الإدارة على «متجر الواحة» دون فقد أي بيانات.
- أضف إلى
customersعمود البريدemailنصيًّا. - أضف إلى
productsعمودis_activeعددًا صحيحًا افتراضيًّا 1. - أعد تسمية عمود
statusفيordersإلىorder_status.
👀 اعرض النتيجة المطلوبة
| name |
|---|
| id |
| name |
| city |
| phone |
| joined |
| id | is_active |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 7 | 1 |
| 8 | 1 |
| 9 | 1 |
| 10 | 1 |
| 11 | 1 |
| 12 | 1 |
| name |
|---|
| id |
| customer_id |
| order_date |
| order_status |
| id | order_status |
|---|---|
| 1 | مُسلَّم |
| 2 | مُسلَّم |
| 3 | مُسلَّم |
| 4 | مُسلَّم |
| 5 | ملغى |
| 6 | مُسلَّم |
| 7 | قيد الشحن |
| 8 | قيد الشحن |
| 9 | جديد |
| 10 | جديد |
| 11 | جديد |
| 12 | جديد |
- الكود يعمل بلا أخطاء
- أعمدة customers صحيحة
- كل المنتجات القديمة صارت نشطة
(1) - أعمدة orders صحيحة
- لم تُفقد أي طلبات
💡 تلميح 1
💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
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;