التعامل مع القيم الفارغة NULL

في عالم قواعد البيانات، القيمة NULL هي مفهوم فريد ومهم جداً يختلف تماماً عن القيم العادية. NULL لا تعني صفراً، ولا تعني نصاً فارغاً، بل تعني "غياب القيمة" أو "قيمة غير معروفة". في هذا الدرس الشامل من سلسلة تعلم لغة SQL باللغة العربية، سنتعلم كيفية التعامل مع NULL بشكل صحيح، الفخاخ الشائعة التي يقع فيها المبتدئون، والدوال المتخصصة للتعامل مع القيم الفارغة.

1. ما هو NULL في SQL؟

NULL هو قيمة خاصة في SQL تشير إلى "عدم وجود قيمة" أو "قيمة غير معروفة". NULL ليس صفراً، وليس نصاً فارغاً، وليس مسافة. إنه حالة خاصة تماماً.

أمثلة واقعية على NULL
  • رقم الهاتف الثاني: إذا كان لديك عميل ليس لديه رقم هاتف ثانٍ، القيمة تكون NULL (وليس صفراً أو فارغاً)
  • تاريخ الانتهاء: موظف لا يزال يعمل، تاريخ انتهاء عمله NULL
  • الخصم: منتج بدون خصم، قيمة الخصم NULL (وليس 0%)
  • البريد الإلكتروني: عميل لم يقدم بريده الإلكتروني، القيمة NULL
تحذير مهم: NULL ≠ 0 و NULL ≠ '' (نص فارغ). هذا الفرق أساسي وحاسم في فهم SQL.
مثال: جدول يحتوي على NULL
جدول employees مع قيم NULL
+----+----------+--------+------------+------------+
| id | name     | salary | phone2     | end_date   |
+----+----------+--------+------------+------------+
| 1  | أحمد     | 5000   | 0501234567 | NULL       |
| 2  | فاطمة    | 6000   | NULL       | NULL       |
| 3  | محمد     | 5500   | 0509876543 | 2024-12-31 |
| 4  | سارة     | 7000   | NULL       | NULL       |
+----+----------+--------+------------+------------+

-- أحمد: لديه رقم هاتف ثانٍ، لا يزال يعمل (end_date = NULL)
-- فاطمة: لا يوجد رقم هاتف ثانٍ (NULL)، لا تزال تعمل
-- محمد: لديه رقم هاتف ثانٍ، سينتهي عقده في 2024-12-31
-- سارة: لا يوجد رقم هاتف ثانٍ، لا تزال تعمل

2. الخطأ الشائع: استخدام = مع NULL

أكبر خطأ يقع فيه المبتدئون هو محاولة مقارنة NULL باستخدام = أو !=. هذا لا يعمل أبداً!

❌ خطأ شائع
-- ❌ خطأ: هذا لن يعمل!
SELECT * FROM employees
WHERE phone2 = NULL;

-- النتيجة: 0 rows (لن يجلب أي شيء!)

-- ❌ خطأ: هذا أيضاً لن يعمل!
SELECT * FROM employees
WHERE phone2 != NULL;
لماذا لا يعمل؟ لأن NULL تعني "غير معروف"، ولا يمكن مقارنة شيء غير معروف بأي قيمة. حتى NULL = NULL تعطي نتيجة غير معروفة (ليست TRUE ولا FALSE).
الطريقة الصحيحة: IS NULL و IS NOT NULL
✅ الطريقة الصحيحة
-- ✅ صحيح: جلب الموظفين الذين ليس لديهم رقم هاتف ثانٍ
SELECT * FROM employees
WHERE phone2 IS NULL;

-- النتيجة:
-- | 2  | فاطمة    | 6000   | NULL       | NULL       |
-- | 4  | سارة     | 7000   | NULL       | NULL       |

-- ✅ صحيح: جلب الموظفين الذين لديهم رقم هاتف ثانٍ
SELECT * FROM employees
WHERE phone2 IS NOT NULL;

-- النتيجة:
-- | 1  | أحمد     | 5000   | 0501234567 | NULL       |
-- | 3  | محمد     | 5500   | 0509876543 | 2024-12-31 |

3. استخدام IS NULL و IS NOT NULL

مثال 1: الموظفون الذين لا يزالون يعملون
الموظفون النشطون
SELECT name, salary FROM employees
WHERE end_date IS NULL;
النتيجة
+----------+--------+
| name     | salary |
+----------+--------+
| أحمد     | 5000   |
| فاطمة    | 6000   |
| سارة     | 7000   |
+----------+--------+
3 rows in set
مثال 2: المنتجات بدون خصم
جدول products
+----+------------------+--------+----------+
| id | name             | price  | discount |
+----+------------------+--------+----------+
| 1  | لابتوب           | 3500   | 10       |
| 2  | ماوس             | 50     | NULL     |
| 3  | شاشة             | 800    | 15       |
| 4  | لوحة مفاتيح      | 120    | NULL     |
+----+------------------+--------+----------+
المنتجات بدون خصم
SELECT name, price FROM products
WHERE discount IS NULL;
النتيجة
+------------------+--------+
| name             | price  |
+------------------+--------+
| ماوس             | 50     |
| لوحة مفاتيح      | 120    |
+------------------+--------+
2 rows in set
مثال 3: دمج مع شروط أخرى
شروط متعددة
-- المنتجات الرخيصة (أقل من 200) بدون خصم
SELECT name, price FROM products
WHERE price < 200 AND discount IS NULL;

-- الموظفون النشطون براتب أعلى من 5500
SELECT name, salary FROM employees
WHERE end_date IS NULL AND salary > 5500;

4. دالة COALESCE - استبدال NULL بقيمة افتراضية

COALESCE هي دالة قوية جداً تأخذ عدة قيم وتُرجع أول قيمة غير NULL. إذا كانت جميع القيم NULL، تُرجع NULL.

البنية الأساسية
COALESCE(value1, value2, value3, ..., default_value)
مثال 1: عرض "لا يوجد" بدلاً من NULL
استبدال NULL بنص
SELECT 
    name,
    COALESCE(phone2, 'لا يوجد') AS phone2
FROM employees;
النتيجة
+----------+------------+
| name     | phone2     |
+----------+------------+
| أحمد     | 0501234567 |
| فاطمة    | لا يوجد    |
| محمد     | 0509876543 |
| سارة     | لا يوجد    |
+----------+------------+
مثال 2: حساب السعر بعد الخصم
معالجة NULL في الحسابات
SELECT 
    name,
    price,
    COALESCE(discount, 0) AS discount,
    price - (price * COALESCE(discount, 0) / 100) AS final_price
FROM products;
النتيجة
+------------------+--------+----------+-------------+
| name             | price  | discount | final_price |
+------------------+--------+----------+-------------+
| لابتوب           | 3500   | 10       | 3150.00     |
| ماوس             | 50     | 0        | 50.00       |
| شاشة             | 800    | 15       | 680.00      |
| لوحة مفاتيح      | 120    | 0        | 120.00      |
+------------------+--------+----------+-------------+
مثال 3: أولويات متعددة
COALESCE مع عدة خيارات
-- جدول contacts مع عدة طرق اتصال
SELECT 
    name,
    COALESCE(mobile, phone, email, 'لا توجد معلومات اتصال') AS contact
FROM contacts;

-- سيعرض أول قيمة غير NULL من: mobile، ثم phone، ثم email
-- إذا كانت جميعها NULL، يعرض "لا توجد معلومات اتصال"

5. دالة IFNULL (MySQL) و ISNULL (SQL Server)

IFNULL في MySQL هي نسخة مبسطة من COALESCE تأخذ معاملين فقط.

البنية الأساسية
-- MySQL
IFNULL(column, default_value)

-- SQL Server
ISNULL(column, default_value)

-- PostgreSQL / Oracle (استخدم COALESCE)
COALESCE(column, default_value)
مثال: IFNULL في MySQL
IFNULL
SELECT 
    name,
    IFNULL(discount, 0) AS discount
FROM products;

-- مطابق لـ:
SELECT 
    name,
    COALESCE(discount, 0) AS discount
FROM products;
نصيحة: استخدم COALESCE لأنها معيارية وتعمل في جميع أنظمة SQL، بينما IFNULL خاصة بـ MySQL فقط.

6. دالة NULLIF - تحويل قيمة إلى NULL

NULLIF تُرجع NULL إذا كانت القيمتان متساويتان، وإلا تُرجع القيمة الأولى.

البنية الأساسية
NULLIF(value1, value2)

-- إذا كان value1 = value2، تُرجع NULL
-- وإلا تُرجع value1
مثال 1: تجنب القسمة على صفر
حماية من القسمة على صفر
-- جدول sales
+----+----------+-------+
| id | product  | qty   |
+----+----------+-------+
| 1  | لابتوب   | 10    |
| 2  | ماوس     | 0     |
| 3  | شاشة     | 5     |
+----+----------+-------+

-- ❌ خطأ: القسمة على صفر ستسبب خطأ
SELECT product, 1000 / qty AS price_per_unit FROM sales;

-- ✅ صحيح: استخدام NULLIF
SELECT 
    product,
    1000 / NULLIF(qty, 0) AS price_per_unit
FROM sales;
النتيجة
+----------+----------------+
| product  | price_per_unit |
+----------+----------------+
| لابتوب   | 100.00         |
| ماوس     | NULL           | ← تجنب القسمة على صفر
| شاشة     | 200.00         |
+----------+----------------+
مثال 2: تحويل قيم فارغة إلى NULL
تنظيف البيانات
-- تحويل النصوص الفارغة إلى NULL
SELECT 
    name,
    NULLIF(email, '') AS email
FROM users;

-- إذا كان email = ''، سيتحول إلى NULL

7. NULL في العمليات الحسابية

قاعدة ذهبية: أي عملية حسابية تحتوي على NULL تُنتج NULL.

NULL في الحسابات
SELECT 
    10 + NULL AS result1,      -- NULL
    10 - NULL AS result2,      -- NULL
    10 * NULL AS result3,      -- NULL
    10 / NULL AS result4,      -- NULL
    CONCAT('Hello ', NULL) AS result5;  -- NULL
مثال عملي: حساب المجموع الكلي
جدول orders
+----+--------+----------+
| id | price  | shipping |
+----+--------+----------+
| 1  | 100    | 10       |
| 2  | 200    | NULL     |
| 3  | 150    | 15       |
+----+--------+----------+
❌ خطأ: سيعطي NULL
SELECT 
    id,
    price + shipping AS total
FROM orders;
النتيجة الخاطئة
+----+-------+
| id | total |
+----+-------+
| 1  | 110   |
| 2  | NULL  | ← مشكلة!
| 3  | 165   |
+----+-------+
✅ الحل: استخدام COALESCE
SELECT 
    id,
    price + COALESCE(shipping, 0) AS total
FROM orders;
النتيجة الصحيحة
+----+-------+
| id | total |
+----+-------+
| 1  | 110   |
| 2  | 200   | ← صحيح!
| 3  | 165   |
+----+-------+

8. NULL في الدوال التجميعية

الدوال التجميعية مثل COUNT, SUM, AVG تتجاهل القيم NULL تلقائياً.

جدول scores
+----+----------+-------+
| id | student  | score |
+----+----------+-------+
| 1  | أحمد     | 85    |
| 2  | فاطمة    | 90    |
| 3  | محمد     | NULL  | ← غائب
| 4  | سارة     | 95    |
| 5  | علي      | NULL  | ← غائب
+----+----------+-------+
الدوال التجميعية مع NULL
SELECT 
    COUNT(*) AS total_students,           -- 5 (كل الطلاب)
    COUNT(score) AS students_attended,    -- 3 (فقط من لديهم درجات)
    SUM(score) AS total_score,            -- 270 (85+90+95)
    AVG(score) AS average_score           -- 90 (270/3)
FROM scores;
النتيجة
+----------------+-------------------+-------------+---------------+
| total_students | students_attended | total_score | average_score |
+----------------+-------------------+-------------+---------------+
| 5              | 3                 | 270         | 90.00         |
+----------------+-------------------+-------------+---------------+

-- لاحظ: AVG حسب المتوسط على 3 طلاب فقط (تجاهل NULL)
تحذير: COUNT(*) يعد جميع الصفوف، بينما COUNT(column) يعد فقط الصفوف التي ليست NULL في ذلك العمود.

9. NULL في ORDER BY

عند الترتيب، سلوك NULL يختلف حسب نظام قاعدة البيانات:

نظام SQL ASC (تصاعدي) DESC (تنازلي)
MySQL NULL في البداية NULL في النهاية
PostgreSQL NULL في النهاية NULL في البداية
SQL Server NULL في البداية NULL في النهاية
التحكم في موضع NULL (PostgreSQL)
NULLS FIRST / NULLS LAST
-- PostgreSQL: وضع NULL في البداية
SELECT * FROM employees
ORDER BY end_date ASC NULLS FIRST;

-- PostgreSQL: وضع NULL في النهاية
SELECT * FROM employees
ORDER BY end_date ASC NULLS LAST;

10. أمثلة عملية متقدمة

مثال 1: تقرير الموظفين الكامل
معالجة شاملة لـ NULL
SELECT 
    name,
    salary,
    COALESCE(phone2, 'غير متوفر') AS phone2,
    COALESCE(email, 'غير متوفر') AS email,
    CASE 
        WHEN end_date IS NULL THEN 'نشط'
        ELSE 'منتهي العقد'
    END AS status,
    COALESCE(end_date, 'لا يزال يعمل') AS end_date
FROM employees;
مثال 2: حساب الإجمالي مع الخصم
فاتورة مع معالجة NULL
SELECT 
    product_name,
    price,
    quantity,
    COALESCE(discount, 0) AS discount,
    COALESCE(tax, 0) AS tax,
    (price * quantity) AS subtotal,
    (price * quantity) * (1 - COALESCE(discount, 0) / 100) AS after_discount,
    (price * quantity) * (1 - COALESCE(discount, 0) / 100) * (1 + COALESCE(tax, 0) / 100) AS total
FROM order_items;
مثال 3: البحث مع NULL
بحث مرن
-- البحث عن منتج: إذا كان الخصم NULL أو أكبر من 10%
SELECT * FROM products
WHERE discount IS NULL OR discount > 10;

-- البحث عن موظف: لديه رقم هاتف ثانٍ أو بريد إلكتروني
SELECT * FROM employees
WHERE phone2 IS NOT NULL OR email IS NOT NULL;
مثال 4: تنظيف البيانات
تحديث القيم NULL
-- تحديث جميع الخصومات NULL إلى 0
UPDATE products
SET discount = 0
WHERE discount IS NULL;

-- تحديث البريد الإلكتروني الفارغ إلى NULL
UPDATE users
SET email = NULL
WHERE email = '';

11. نصائح وأفضل الممارسات

1. لا تستخدم = أو != مع NULL أبداً
القاعدة الذهبية
-- ❌ خطأ
WHERE column = NULL
WHERE column != NULL

-- ✅ صحيح
WHERE column IS NULL
WHERE column IS NOT NULL
2. استخدم COALESCE في الحسابات

دائماً استخدم COALESCE عند إجراء عمليات حسابية على أعمدة قد تحتوي على NULL.

3. حدد القيم الافتراضية في التصميم
DEFAULT في CREATE TABLE
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    discount DECIMAL(5,2) DEFAULT 0,  -- قيمة افتراضية بدلاً من NULL
    stock INT DEFAULT 0
);
4. استخدم NOT NULL عندما يكون ذلك منطقياً

إذا كان العمود يجب أن يحتوي دائماً على قيمة، استخدم NOT NULL في تعريف الجدول.

5. وثّق سلوك NULL في قاعدة بياناتك

اكتب تعليقات توضح ماذا يعني NULL في كل عمود (غير معروف، غير متوفر، غير مطبق، إلخ).

ملخص الدرس
  • NULL: تعني "غياب القيمة" أو "قيمة غير معروفة"
  • المقارنة: استخدم IS NULL و IS NOT NULL (وليس = أو !=)
  • COALESCE: استبدال NULL بقيمة افتراضية
  • IFNULL: نسخة مبسطة من COALESCE (MySQL فقط)
  • NULLIF: تحويل قيمة معينة إلى NULL
  • الحسابات: أي عملية مع NULL تُنتج NULL
  • الدوال التجميعية: تتجاهل NULL تلقائياً
  • Best Practice: استخدم COALESCE في الحسابات وحدد قيم افتراضية

الخطوة التالية: الدوال التجميعية (Aggregate Functions)

أكمل رحلتك التعليمية وانتقل إلى الدرس التالي لتعلم الدوال التجميعية (Aggregate Functions) وتطوير مهاراتك في قواعد البيانات.

الانتقال إلى الدرس التالي
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن