العروض في MySQL: CREATE VIEW مع IF و CASE
استعلام «تفاصيل الطلبات» في متجرنا يربط ثلاثة جداول ويحسب الإجمالي. هل ستكتبه من جديد في كل صفحة وكل تقرير؟ وماذا لو تغيّرت طريقة الحساب؟ العرض (View) يحل المشكلة: استعلام محفوظ باسم، تتعامل معه كأنه جدول. في هذا الدرس ستتعلم إنشاء العروض، ومعها IF و CASE لإضافة أعمدة محسوبة مفيدة.
IF و CASE: أعمدة بمنطق شرطي
Section titled “IF و CASE: أعمدة بمنطق شرطي”قبل العروض، نحتاج أداتين. الدالة IF خاصة بـ MySQL وتأخذ شرطاً وقيمتين:
SELECT name, price, IF(price > 200, 'غالٍ', 'عادي') AS level FROM products;الناتج:
| name | price | level |
|---|---|---|
| كتاب البرمجة للمبتدئين | 108.00 | عادي |
| سماعة لاسلكية | 450.50 | غالٍ |
| حقيبة مدرسية | 280.00 | غالٍ |
| آلة حاسبة علمية | 199.99 | عادي |
| قصص الأطفال | 58.50 | عادي |
| مجموعة أقلام | 35.75 | عادي |
IF(شرط, قيمة إذا تحقق, قيمة إذا لم يتحقق). ولأكثر من حالتين نستخدم CASE القياسية، وهي تفحص الشروط بالترتيب وتُرجع قيمة أول شرط يتحقق:
SELECT name, stock, CASE WHEN stock = 0 THEN 'غير متوفر' WHEN stock < 10 THEN 'كمية محدودة' ELSE 'متوفر' END AS statusFROM products;الناتج:
| name | stock | status |
|---|---|---|
| كتاب البرمجة للمبتدئين | 15 | متوفر |
| سماعة لاسلكية | 7 | كمية محدودة |
| حقيبة مدرسية | 0 | غير متوفر |
| آلة حاسبة علمية | 20 | متوفر |
| قصص الأطفال | 30 | متوفر |
| مجموعة أقلام | 50 | متوفر |
هذه هي الشارة التي تراها تحت كل منتج في أي متجر إلكتروني.
إنشاء عرض
Section titled “إنشاء عرض”قاعدة «متى نقول كمية محدودة؟» ستحتاجها صفحة المنتج، ولوحة التحكم، وتقرير المخزون. بدل نسخ CASE في كل مكان، احفظها مرة واحدة:
CREATE VIEW product_status ASSELECT id, name, price, stock, CASE WHEN stock = 0 THEN 'غير متوفر' WHEN stock < 10 THEN 'كمية محدودة' ELSE 'متوفر' END AS statusFROM products;والآن استعلم منه كأي جدول:
SELECT name, status FROM product_status WHERE status <> 'متوفر';الناتج:
| name | status |
|---|---|
| سماعة لاسلكية | كمية محدودة |
| حقيبة مدرسية | غير متوفر |
لاحظ أننا صفّينا بالعمود المحسوب status مباشرة، وهذا غير ممكن في الاستعلام الأصلي دون تكرار CASE في WHERE. ويعمل معه التجميع أيضاً:
SELECT status, COUNT(*) AS items FROM product_status GROUP BY status;الناتج:
| status | items |
|---|---|
| غير متوفر | 1 |
| كمية محدودة | 1 |
| متوفر | 4 |
العرض مثل نافذة على الجداول: لا يخزن بيانات، بل يريك البيانات الأصلية من زاوية معيّنة.
العرض حي دائماً
Section titled “العرض حي دائماً”لأن العرض لا يخزن شيئاً، فهو يعكس أي تغيير في الجدول الأصلي فوراً. جرّبنا داخل معاملة تصفير مخزون الأقلام:
START TRANSACTION;UPDATE products SET stock = 0 WHERE id = 6;SELECT name, stock, status FROM product_status WHERE id = 6;الناتج:
| name | stock | status |
|---|---|---|
| مجموعة أقلام | 0 | غير متوفر |
تغيّرت الحالة في العرض تلقائياً. وبعد ROLLBACK; عاد المخزون 50 والحالة «متوفر». في كل مرة تستعلم من العرض، تنفّذ MySQL استعلامه الأصلي من جديد.
عرض يخفي الربط
Section titled “عرض يخفي الربط”هنا الفائدة الأكبر: إخفاء JOIN معقد خلف اسم بسيط.
CREATE VIEW order_details ASSELECT o.id AS order_id, c.name AS customer, p.name AS product, o.quantity, o.quantity * p.price AS total, o.order_dateFROM orders oJOIN customers c ON c.id = o.customer_idJOIN products p ON p.id = o.product_id;SELECT customer, product, total FROM order_detailsWHERE order_date >= '2026-11-01';الناتج:
| customer | product | total |
|---|---|---|
| سارة | مجموعة أقلام | 71.50 |
| عمر | كتاب البرمجة للمبتدئين | 108.00 |
وتقرير «كبار العملاء» أصبح سطرين بلا أي ربط ظاهر:
SELECT customer, COUNT(*) AS orders_count, SUM(total) AS spentFROM order_detailsGROUP BY customerORDER BY spent DESC;الناتج:
| customer | orders_count | spent |
|---|---|---|
| عمر | 2 | 1009.00 |
| سارة | 3 | 379.49 |
وإذا تغيّرت طريقة حساب الإجمالي غداً (ضريبة أو خصم مثلاً)، تعدّل العرض فقط، وكل الاستعلامات التي تستخدمه تأخذ الحساب الجديد.
أين العروض؟
Section titled “أين العروض؟”SHOW FULL TABLES;الناتج:
| Tables_in_shop | Table_type |
|---|---|
| customers | BASE TABLE |
| order_details | VIEW |
| orders | BASE TABLE |
| product_status | VIEW |
| products | BASE TABLE |
| subscribers | BASE TABLE |
العروض تظهر مع الجداول، والعمود Table_type يفرّق بينهما. ولهذا لا يمكن أن يحمل عرض وجدول الاسم نفسه. ولرؤية الاستعلام المحفوظ داخل عرض: SHOW CREATE VIEW product_status;.
تعديل العرض وحذفه
Section titled “تعديل العرض وحذفه”CREATE OR REPLACE VIEW تنشئ العرض أو تستبدل تعريفه إن كان موجوداً. هنا نضيف عمود التصنيف:
CREATE OR REPLACE VIEW product_status ASSELECT id, name, category, price, stock, CASE WHEN stock = 0 THEN 'غير متوفر' WHEN stock < 10 THEN 'كمية محدودة' ELSE 'متوفر' END AS statusFROM products;والحذف بـ DROP VIEW product_status;. حذف العرض لا يحذف أي بيانات، فالبيانات في الجداول الأصلية.
هل يمكن التعديل عبر العرض؟
Section titled “هل يمكن التعديل عبر العرض؟”العرض البسيط المبني على جدول واحد دون تجميع قابل للتعديل: UPDATE عليه يغيّر الجدول الأصلي. أنشأنا عرضاً للمنتجات الأرخص من 100 وجرّبنا داخل معاملة:
CREATE VIEW cheap_products ASSELECT id, name, price FROM products WHERE price < 100;
UPDATE cheap_products SET price = 40 WHERE id = 6;فأصبح سعر الأقلام في جدول products نفسه 40.00 (ثم تراجعنا). أما الأعمدة المحسوبة فلا يمكن تعديلها:
UPDATE order_details SET total = 0 WHERE order_id = 1;الناتج: ERROR 1348 (HY000): Column 'total' is not updatable
وهذا منطقي: total ناتج ضرب، فأي الطرفين ستغيّر MySQL؟ والعروض التي فيها GROUP BY أو DISTINCT أو دوال تجميع للقراءة فقط كلها.
جرّب بنفسك
Section titled “جرّب بنفسك”- أنشئ عرضاً
booksيعرض اسم وسعر المنتجات التي تصنيفها «كتب» فقط. - أنشئ عرضاً
products_with_taxفيه الاسم والسعر وعمودwith_taxيساوي السعر مضروباً في 1.14. - استخدم العرض
order_detailsلمعرفة المنتج الأكثر مبيعاً (مجموع الكميات). - تحدٍّ: أنشئ عرضاً
customer_summaryيعرض لكل عميل عدد طلباته، معLEFT JOINحتى يظهر كريم بصفر، وعمودkindقيمته «نشط» أو «جديد» باستخدامIF.
أخطاء شائعة
Section titled “أخطاء شائعة”- اسم مستخدَم: إنشاء عرض باسم موجود يعطي
ERROR 1050 (42S01): Table 'cheap_products' already exists. استخدمCREATE OR REPLACE VIEW. - الظن بأن العرض أسرع: العرض لا يخزن النتيجة، بل ينفّذ استعلامه في كل مرة. هو يبسّط الكود ولا يسرّعه.
- حذف عمود يعتمد عليه عرض: يبقى العرض موجوداً لكنه يعطي خطأ عند استخدامه. راجع العروض قبل تعديل بنية الجداول.
- عروض فوق عروض فوق عروض: تصعب معرفة ما يحدث فعلاً ويبطؤ الأداء. اجعلها طبقة واحدة أو اثنتين.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ماذا يخزن العرض View في قاعدة البيانات؟
العرض استعلام محفوظ باسم، ولذلك يعرض البيانات الحالية دائماً ولا يأخذ مساحة للبيانات.
سؤال
ما ناتج IF(5 > 3, 'نعم', 'لا')؟
الشرط متحقق، فتُرجع الدالة القيمة الثانية في ترتيب المعاملات، أي قيمة حالة التحقق.
الخلاصة
Section titled “الخلاصة”IF(شرط, أ, ب)لحالتين، وCASE WHEN ... ENDلعدة حالات.CREATE VIEW name AS SELECT ...يحفظ الاستعلام باسم يُستخدم كجدول.- العرض لا يخزن بيانات: يعكس التغييرات فوراً ويُنفَّذ عند كل استخدام.
- العروض تخفي الربط والحسابات المعقدة وتوحّدها في مكان واحد.
- العرض البسيط قابل للتعديل، والأعمدة المحسوبة والعروض التجميعية للقراءة فقط.