الدوال المتقدمة

الدوال المتقدمة

🌍 تشبيه من العالم האמיתי

SQL تشبه السويس.army knife — بالإضافة إلى "السكين" (الاستعلامات) و"المنشار" (التجميع) اللذين تعلمتهم بالفعل، لديها العديد من الأدوات المفيدة الأخرى:

إتقان هذه الدوال يتيح لك إجراء المزيد من معالجة البيانات في SQL، مما يقلل الحاجة إلى معالجة إضافية في طبقة التطبيق.


🎯 المفاهيم الأساسية

دوال النصوص

CONCAT — ربط النصوص

يجمع عدة نصوص في نص واحد.

SQL
-- ربط الاسم
SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM employees;

-- MySQL يدعم أيضًا || للربط (يتطلب تفعيل PIPES_AS_CONCAT)
-- SELECT first_name || ' ' || last_name FROM employees;

SUBSTRING — استخراج جزء من النص

يستخرج جزءًا من النص.

SQL
-- استخراج جزء اسم المستخدم من البريد الإلكتروني (قبل @)
SELECT email, SUBSTRING(email, 1, POSITION('@' IN email) - 1) AS username
FROM employees
WHERE email IS NOT NULL;

-- استخراج بسيط: ابدأ من الموضع 1، خذ 3 أحرف
SELECT SUBSTRING('Hello World', 1, 3);  -- النتيجة: Hel

UPPER / LOWER — تحويل حالة الأحرف

SQL
SELECT UPPER('hello') AS uppercase, LOWER('WORLD') AS lowercase;
-- النتيجة: HELLO, world

-- استخدام عملي: بحث غير حساس لحالة الأحرف
SELECT * FROM employees WHERE LOWER(email) = 'zhangsan@company.com';

TRIM — إزالة المسافات

SQL
-- إزالة المسافات من البداية والنهاية
SELECT TRIM('  hello  ') AS trimmed;  -- النتيجة: hello

-- إزالة أحرف محددة
SELECT TRIM(LEADING '0' FROM '0012300');  -- النتيجة: 12300

REPLACE — استبدال النصوص

SQL
-- إخفاء الأرقام الأربعة الوسطى من رقم الهاتف بـ ****
SELECT phone, REPLACE(phone, SUBSTRING(phone, 4, 4), '****') AS masked
FROM employees;

LENGTH — طول النص

SQL
SELECT first_name, LENGTH(first_name) AS name_len
FROM employees;

دوال الأرقام

ROUND — التقريب

SQL
SELECT ROUND(3.14159, 2);   -- النتيجة: 3.14
SELECT ROUND(3.14159, 0);   -- النتيجة: 3
SELECT ROUND(1234.5, -2);   -- النتيجة: 1200 (تقريب للمئات)

CEIL / FLOOR — التقريب للأعلى / للأسفل

SQL
SELECT CEIL(3.1);    -- النتيجة: 4 (تقريب للأعلى)
SELECT CEIL(3.0);    -- النتيجة: 3
SELECT FLOOR(3.9);   -- النتيجة: 3 (تقريب للأسفل)
SELECT FLOOR(3.0);   -- النتيجة: 3
💡 ملاحظة: تختلف أسماء الدوال عبر قواعد البيانات. يستخدم SQL Server CEILING()، وOracle يستخدم CEIL().

ABS — القيمة المطلقة

SQL
SELECT ABS(-100);    -- النتيجة: 100
SELECT ABS(50);      -- النتيجة: 50

MOD — باقي القسمة

SQL
SELECT MOD(10, 3);   -- النتيجة: 1
SELECT MOD(100, 7);  -- النتيجة: 2

-- SQL Server لا يدعم دالة MOD، استخدم % بدلاً من ذلك
-- SELECT 10 % 3;    -- النتيجة: 1

دوال التواريخ

NOW — التاريخ والوقت الحالي

SQL
SELECT NOW();        -- النتيجة: 2026-06-28 14:30:00 (الوقت الحالي)
SELECT CURDATE();    -- النتيجة: 2026-06-28 (التاريخ فقط)
SELECT CURTIME();    -- النتيجة: 14:30:00 (الوقت فقط)
💡 ملاحظة: يستخدم SQL Server GETDATE() بدلاً من NOW().

DATE — استخراج جزء التاريخ

SQL
SELECT DATE(NOW());  -- النتيجة: 2026-06-28

-- استخراج السنة والشهر واليوم
SELECT EXTRACT(YEAR FROM order_date) AS year,
       EXTRACT(MONTH FROM order_date) AS month,
       EXTRACT(DAY FROM order_date) AS day
FROM orders;

DATEDIFF — الفرق بين التواريخ

SQL
-- حساب عدد الأيام بين تاريخين
SELECT DATEDIFF('2026-12-31', '2026-01-01');  -- النتيجة: 364

-- حساب مدة خدمة الموظف بالأيام
SELECT first_name, hire_date,
       DATEDIFF(CURDATE(), hire_date) AS tenure_days
FROM employees;
💡 ملاحظة: DATEDIFF(date1, date2) في MySQL يحسب date1 - date2. يستخدم SQL Server نفس الترتيب. PostgreSQL يستخدم date1 - date2 للطرح المباشر.

DATE_FORMAT — تنسيق التاريخ

SQL
-- MySQL
SELECT DATE_FORMAT(order_date, '%Y-%m-%d') AS formatted_date
FROM orders;

-- SQL Server
-- SELECT FORMAT(order_date, 'yyyy-MM-dd') FROM orders;

EXTRACT — استخراج أجزاء التاريخ

SQL
SELECT EXTRACT(YEAR FROM order_date) AS year,
       EXTRACT(MONTH FROM order_date) AS month,
       EXTRACT(DAY FROM order_date) AS day,
       EXTRACT(HOUR FROM NOW()) AS hour
FROM orders;

تحويل الأنواع

CAST — تحويل النوع (SQL قياسي)

SQL
-- نص إلى عدد صحيح
SELECT CAST('123' AS SIGNED INTEGER);  -- MySQL
SELECT CAST('123' AS INT);             -- SQL Server

-- عدد إلى نص
SELECT CAST(12345 AS CHAR);

-- تاريخ إلى نص
SELECT CAST(order_date AS CHAR) FROM orders;

-- نص إلى تاريخ
SELECT CAST('2026-06-28' AS DATE);

CONVERT — تحويل النوع (MySQL / SQL Server)

SQL
-- MySQL
SELECT CONVERT('123', SIGNED INTEGER);
SELECT CONVERT(123, CHAR);

-- SQL Server
SELECT CONVERT(INT, '123');
SELECT CONVERT(VARCHAR, 12345);
💡 توصية: CAST هو المعيار في SQL وله توافق أفضل — يُوصى به. يختلف CONVERT اختلافًا كبيرًا في الصيغة عبر قواعد البيانات.


📝 الصيغة الأساسية

SQL
-- دوال النصوص
SELECT CONCAT(string1, string2) AS concatenated,
       SUBSTRING(string, start_position, length) AS extracted,
       UPPER(string) AS uppercase,
       LOWER(string) AS lowercase,
       TRIM(string) AS trimmed,
       REPLACE(string, old_value, new_value) AS replaced,
       LENGTH(string) AS length;

-- دوال الأرقام
SELECT ROUND(number, decimal_places) AS rounded,
       CEIL(number) AS rounded_up,
       FLOOR(number) AS rounded_down,
       ABS(number) AS absolute,
       MOD(number1, number2) AS remainder;

-- دوال التواريخ
SELECT NOW() AS current_time,
       CURDATE() AS current_date,
       DATEDIFF(date1, date2) AS day_difference,
       EXTRACT(YEAR FROM date) AS year;

-- تحويل الأنواع
SELECT CAST(value AS target_type) AS converted;
💡 نصيحة:

  • قد تختلف أسماء الدوال والمعاملات عبر قواعد البيانات — راجع التوثيق المقابل قبل الاستخدام
  • CAST هو المعيار في SQL ويُوصى به؛ يختلف CONVERT في الصيغة بين MySQL و SQL Server
  • دوال التواريخ هي الأكثر اختلافًا — انتبه بشكل خاص عند التطوير عبر قواعد البيانات

📌 أمثلة

مثال: معالجة النصوص — تنسيق معلومات الموظفين

SQL
SELECT 
    CONCAT(UPPER(last_name), ', ', first_name) AS name,
    LOWER(email) AS email,
    SUBSTRING(phone, 1, 3) AS area_code,
    LENGTH(first_name) AS first_name_length,
    REPLACE(department_id, NULL, 'Unassigned') AS department
FROM employees
ORDER BY last_name;
▶ جرّب الكود

الناتج:

TEXT
name          email                   area_code  first_name_length  department
-----------  ----------------------  ---------  -----------------  ----------
LI, Si       lisi@company.com        138        2                  2
WANG, Wu     wangwu@company.com      139        2                  2
ZHANG, San   zhangsan@company.com    137        2                  1
💡 التفسير: CONCAT + UPPER يقوم بتنسيق الاسم، LOWER يوحّد البريد الإلكتروني إلى أحرف صغيرة، SUBSTRING يستخرج أول 3 أرقام من رقم الهاتف.


مثال: الحسابات الرقمية — معالجة مبالغ الطلبات

SQL
SELECT 
    order_id,
    total_amount AS original_amount,
    ROUND(total_amount * 0.9, 2) AS discounted_amount,
    CEIL(total_amount / 1000) AS thousands_ceil,
    FLOOR(total_amount / 1000) AS thousands_floor,
    MOD(total_amount, 100) AS remainder
FROM orders
WHERE status = 'completed';
▶ جرّب الكود

الناتج:

TEXT
order_id  original_amount  discounted_amount  thousands_ceil  thousands_floor  remainder
--------  --------------  -----------------  --------------  ---------------  ---------
1         15000.00        13500.00           15              15               0.00
2         8500.00         7650.00            9               8                0.00
3         3200.00         2880.00            4               3                0.00
💡 التفسير: ROUND يحسب السعر بعد خصم 10%، CEIL و FLOOR يقومان بالتريب للأعلى والأسفل إلى أقرب ألف على التوالي، MOD يحسب الباقي.


مثال: حساب التواريخ + تحويل الأنواع

SQL
SELECT 
    first_name AS name,
    hire_date AS hire_date,
    DATEDIFF(CURDATE(), hire_date) AS tenure_days,
    EXTRACT(YEAR FROM hire_date) AS hire_year,
    CONCAT(CAST(salary AS CHAR), ' yuan') AS salary_display,
    DATE_FORMAT(hire_date, '%Y-%m') AS hire_month
FROM employees
ORDER BY hire_date;
▶ جرّب الكود

الناتج:

TEXT
name     hire_date   tenure_days  hire_year  salary_display  hire_month
------   ----------  -----------  ---------  --------------  ----------
Zhang    2023-03-15  1199         2023       15000.00 yuan   2023-03
Li       2023-07-01  1089         2023       18000.00 yuan   2023-07
Wang     2024-01-10  899          2024       12000.00 yuan   2024-01
💡 التفسير: DATEDIFF يحسب مدة الخدمة بالأيام، EXTRACT يستخرج السنة، CAST يتحويل الراتب إلى نص قبل ربط الوحدة، DATE_FORMAT يقوم بتنسيق التاريخ.


🎬 سيناريوهات تطبيقية

السيناريو 1: تنظيف البيانات — توحيد الصيغ

البيانات في قاعدة البيانات بصيغ غير متسقة وتحتاج إلى تنظيف للعرض.

SQL
SELECT 
    employee_id,
    CONCAT(UPPER(TRIM(last_name)), ', ', TRIM(first_name)) AS standard_name,
    LOWER(TRIM(email)) AS standard_email,
    REPLACE(REPLACE(phone, '-', ''), ' ', '') AS standard_phone,
    CAST(salary AS DECIMAL(10,2)) AS standard_salary
FROM employees
WHERE email IS NOT NULL;
💡 النهج: TRIM يزيل المسافات الزائدة، UPPER/LOWER يوحّد حالة الأحرف، REPLACE ينظف الأحرف الخاصة من أرقام الهواتف، CAST يضمن اتساق أنواع البيانات.

السيناريو 2: الإحصائيات التقاريرية — تحليل على أساس الوقت

تحليل بيانات الطلبات حسب الربع.

SQL
SELECT 
    EXTRACT(YEAR FROM order_date) AS year,
    CEIL(EXTRACT(MONTH FROM order_date) / 3.0) AS quarter,
    COUNT(*) AS order_count,
    ROUND(SUM(total_amount), 2) AS total_amount,
    ROUND(AVG(total_amount), 2) AS avg_order_amount,
    DATEDIFF(MAX(order_date), MIN(order_date)) AS span_days
FROM orders
WHERE status != 'cancelled'
GROUP BY EXTRACT(YEAR FROM order_date), CEIL(EXTRACT(MONTH FROM order_date) / 3.0)
ORDER BY year, quarter;
💡 النهج: CEIL(MONTH / 3.0) يحول الأشهر إلى أرباع (1-3→Q1، 4-6→Q2، إلخ). DATEDIFF يحسب المدة الزمنية لكل ربع.


❓ أسئلة شائعة

س: ماذا يحدث عندما يواجه CONCAT قيمة NULL? ج: في MySQL، يُرجع CONCAT القيمة NULL عندما يواجه NULL. لمعاملة NULL كنص فارغ، استخدم COALESCE: CONCAT(COALESCE(first_name, ''), ' ', last_name). في PostgreSQL، يُرجع عامل || أيضًا NULL عند مواجهة NULL.

س: ما الفرق بين ROUND و CEIL/FLOOR? ج: ROUND يُقرب إلى عدد محدد من المنازل العشرية، CEIL يُقرب لأقرب عدد صحيح للأعلى، و FLOOR يُقرب لأقرب عدد صحيح للأسفل. على سبيل المثال، 3.5: ROUND(3.5) = 4، CEIL(3.1) = 4، FLOOR(3.9) = 3.

س: هل تختلف دوال التواريخ اختلافًا كبيرًا عبر قواعد البيانات? ج: نعم، الاختلافات كبيرة. يستخدم MySQL NOW() و DATEDIFF() و DATE_FORMAT()؛ يستخدم SQL Server GETDATE() و DATEDIFF() و FORMAT()؛ يستخدم PostgreSQL NOW() وطرح التواريخ و TO_CHAR(). راجع التوثيق المقابل عند التطوير عبر قواعد البيانات.

س: هل أستخدم CAST أم CONVERT? ج: استخدم CAST — وهو المعيار في SQL وتدعمه جميع قواعد البيانات الرئيسية. يختلف CONVERT في الصيغة بين MySQL و SQL Server، مما ينتج عنه توافق أسوأ.


📖 ملخص

الفئة الدوال الشائعة الغرض
النصوص CONCAT, SUBSTRING, UPPER, LOWER, TRIM, REPLACE, LENGTH الربط، الاستخراج، التحويل، التنظيف
الأرقام ROUND, CEIL, FLOOR, ABS, MOD التقريب، التقريب للأسفل، باقي القسمة
التواريخ NOW, CURDATE, DATEDIFF, EXTRACT, DATE_FORMAT الحصول على الوقت، حساب الفروقات، استخراج الأجزاء
تحويل الأنواع CAST, CONVERT تحويل نوع البيانات

📝 تمارين

التمرين 1 (⭐): استعلم من جدول employees، اربط first_name و last_name في اسم كامل (أحرف كبيرة)، واحسب مدة خدمة كل شخص بالأيام.

التمرين 2 (⭐⭐): استعلم من جدول orders، جمّع عدد الطلبات والمبلغ الإجمالي حسب الشهر، باستخدام EXTRACT لاستخراج السنة والشهر، و ROUND للحفاظ على منزلتين عشريتين.

التمرين 3 (⭐⭐⭐): استعلم من جدول employees لإنشاء "بطاقة عمل للموظف" بالصيغة: [القسم] الاسم (سنة التعيين) - الراتب الشهري: xxxxx وحدة. استخدم دوال النصوص للربط و CAST لتحويل الأرقام إلى نصوص.


الدرس التالي

👉 16-case-when - التعبيرات الشرطية: تعلّم التعبيرات الشرطية CASE WHEN وإتقان المنطق الشرطي في SQL!

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%