PostgreSQL: دوال PostgreSQL المدمجة: دليل مفصل
آخر تحديث: 2026-08-26
1. ما ستتعلمه
- دوال الرياضيات:
ABS / ROUND / CEIL / FLOOR / MOD / POWER / SQRT - دوال السلاسل:
LENGTH / CONCAT / LOWER / UPPER / TRIM / SUBSTRING / REPLACE / SPLIT_PART / LEFT / RIGHT - دوال التاريخ:
NOW / CURRENT_DATE / AGE / EXTRACT / DATE_TRUNC / TO_CHAR / TO_DATE - الدوال الشرطية:
COALESCE / NULLIF / GREATEST / LEAST - دوال التسلسل:
NEXTVAL / CURRVAL / SETVAL - تقنيات دمج الدوال
2. القصة
Alice هي محللة بيانات تجارة إلكترونية تحتاج إلى إنشاء تقرير مبيعات شهري في نهاية الشهر. يجب أن يقوم التقرير بما يلي:
- تنسيق
order_dateكـ2025-June-30 - ربط اسم العميل + رقم الطلب في عنوان صف التقرير
- معالجة NULL: قيم الخصم المفقودة افتراضيًا 0
- حساب المال: إجمالي دقيق مع الضريبة والصافي بعد الخصم
- استخدام التسلسل: توليد أرقام متسلسلة لصفوف التقرير
تحتاج Alice إلى دمج دوال PostgreSQL المدمجة لإنتاج التقرير.
3. المفهوم: دوال الرياضيات
(1) دوال الرياضيات الأساسية
| الدالة | المعنى | مثال | النتيجة |
|---|---|---|---|
ABS(x) |
القيمة المطلقة | ABS(-15) |
15 |
ROUND(x, n) |
تقريب إلى n منزلة عشرية | ROUND(3.1415, 2) |
3.14 |
CEIL(x) |
تقريب لأعلى | CEIL(3.2) |
4 |
FLOOR(x) |
تقريب لأسفل | FLOOR(3.8) |
3 |
MOD(x, y) |
باقي القسمة | MOD(10, 3) |
1 |
POWER(x, y) |
الأس | POWER(2, 10) |
1024 |
SQRT(x) |
الجذر التربيعي | SQRT(144) |
12 |
SIGN(x) |
الإشارة | SIGN(-5) |
-1 |
TRUNC(x, n) |
اقتطاع | TRUNC(3.1415, 2) |
3.14 |
(1) ▶ مثال
SELECT
unit_price,
ROUND(unit_price, 0) AS rounded_0,
ROUND(unit_price, 2) AS rounded_2
FROM products
WHERE category = 'Electronics';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(2) ▶ مثال
SELECT
total_amount,
CEIL(total_amount) AS ceil_value,
FLOOR(total_amount) AS floor_value,
total_amount - FLOOR(total_amount) AS decimal_part
FROM orders
WHERE order_status = 'completed';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(2) ROUND مقابل TRUNC مقابل CEIL/FLOOR
| الدالة | السلوك | نتيجة 3.5 |
نتيجة 3.2 |
نتيجة -3.5 |
|---|---|---|---|---|
ROUND(x) |
تقريب لأقرب عدد صحيح | 4 | 3 | -4 |
TRUNC(x) |
اقتطاع الكسور | 3 | 3 | -3 |
CEIL(x) |
تقريب لأعلى | 4 | 4 | -3 |
FLOOR(x) |
تقريب ل��سفل | 3 | 3 | -4 |
(3) ▶ مثال
SELECT
order_id,
total_amount,
MOD(order_id, 10) AS partition_key,
total_amount * POWER(1.08, 1) AS with_annual_tax
FROM orders
WHERE order_status = 'completed';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(4) ▶ مثال
SELECT
unit_price,
SQRT(unit_price) AS price_sqrt,
POWER(unit_price, 1.0 / 3) AS price_cbrt
FROM products
WHERE unit_price > 0
ORDER BY unit_price DESC;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
4. المفهوم: دوال السلاسل
(1) الحالة والطول
| الدالة | المعنى | مثال | النتيجة |
|---|---|---|---|
LOWER(s) |
إلى أحرف صغيرة | LOWER('Hello') |
hello |
UPPER(s) |
إلى أحرف كبيرة | UPPER('Hello') |
HELLO |
INITCAP(s) |
تكبير أول حرف | INITCAP('hello world') |
Hello World |
LENGTH(s) |
عدد الأحرف | LENGTH('PostgreSQL') |
10 |
BIT_LENGTH(s) |
طول البت | BIT_LENGTH('A') |
8 |
CHAR_LENGTH(s) |
نفس LENGTH | CHAR_LENGTH('ABC') |
3 |
(5) ▶ مثال
SELECT
product_name,
LOWER(product_name) AS lower_name,
UPPER(product_name) AS upper_name,
INITCAP(LOWER(product_name)) AS title_name
FROM products
WHERE is_active = true;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(2) الربط والسلاسل الجزئية
| الدالة | المعنى | مثال | النتيجة |
|---|---|---|---|
CONCAT(s1, s2, ...) |
ربط (آمن مع NULL) | CONCAT('A', NULL, 'B') |
AB |
CONCAT_WS(sep, s1, s2) |
ربط بفاصل | CONCAT_WS('-', 'A','B') |
A-B |
s1 || s2 |
ربط (غير آمن مع NULL) | 'A' || NULL |
NULL |
SUBSTRING(s FROM n FOR len) |
سلسلة جزئية | SUBSTRING('Hello' FROM 2 FOR 3) |
ell |
LEFT(s, n) |
n حرف من اليسار | LEFT('Hello', 3) |
Hel |
RIGHT(s, n) |
n حرف من اليمين | RIGHT('Hello', 2) |
lo |
(6) ▶ مثال
SELECT
product_name,
CONCAT(product_name, ' - $', unit_price) AS safe_concat,
product_name || ' - $' || unit_price AS unsafe_concat,
CONCAT_WS(' | ', product_name, category, unit_price::TEXT) AS ws_concat
FROM products;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(3) البحث والاستبدال
| الدالة | المعنى | مثال | النتيجة |
|---|---|---|---|
POSITION(sub IN s) |
إيجاد الموضع | POSITION('sql' IN 'postgresql') |
8 |
STRPOS(s, sub) |
نفس الشيء | STRPOS('postgresql', 'sql') |
8 |
REPLACE(s, from, to) |
استبدال | REPLACE('ABC', 'B', 'X') |
AXC |
OVERLAY(s PLACING t FROM n) |
كتابة فوقية | OVERLAY('XXXX' PLACING 'AB' FROM 2) |
XABX |
SPLIT_PART(s, delim, n) |
تقسيم بمحدد | SPLIT_PART('A-B-C', '-', 2) |
B |
TRIM(s) |
قص المسافات المحيطة | TRIM(' Hi ') |
Hi |
LTRIM(s) |
قص المسافات اليسرى | LTRIM(' Hi ') |
Hi |
RTRIM(s) |
قص المسافات اليمنى | RTRIM(' Hi ') |
Hi |
RPAD(s, len, fill) |
حشو يمين | RPAD('Hi', 5, 'x') |
Hixxx |
LPAD(s, len, fill) |
حشو يسار | LPAD('42', 5, '0') |
00042 |
REVERSE(s) |
عكس | REVERSE('ABC') |
CBA |
(7) ▶ مثال
SELECT
product_name,
SPLIT_PART(category_path, '/', 1) AS top_category,
SPLIT_PART(category_path, '/', 2) AS sub_category
FROM products
WHERE category_path LIKE '%/%';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(8) ▶ مثال
SELECT
TRIM(product_name) AS clean_name,
REPLACE(product_name, ' ', ' ') AS no_double_spaces
FROM products
WHERE is_active = true;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(9) ▶ مثال
SELECT
LPAD(product_id::TEXT, 8, '0') AS formatted_id,
product_name,
unit_price
FROM products
ORDER BY product_id;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
5. المفهوم: دوال التاريخ
(1) الحصول على الوقت الحالي
| الدالة | نوع الإرجاع | الوصف |
|---|---|---|
CURRENT_DATE |
DATE | التاريخ الحالي |
CURRENT_TIME |
TIME WITH TZ | الوقت الحالي (مع المنطقة الزمنية) |
CURRENT_TIMESTAMP |
TIMESTAMP WITH TZ | التاريخ والوقت الحالي |
NOW() |
TIMESTAMP WITH TZ | نفس CURRENT_TIMESTAMP |
LOCALTIMESTAMP |
TIMESTAMP | الوقت الحالي (بدون منطقة زمنية) |
CLOCK_TIMESTAMP() |
TIMESTAMP WITH TZ | ساعة الوقت الفعلي (تتغير لكل استدعاء) |
(10) ▶ مثال
SELECT
CURRENT_DATE AS today,
CURRENT_TIMESTAMP AS now_ts,
NOW() AS now_func,
LOCALTIMESTAMP AS local_ts;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(2) حساب التاريخ
| التعبير | المعنى | مثال النتيجة |
|---|---|---|
DATE '2025-01-15' + 7 |
إضافة أيام | 2025-01-22 |
DATE '2025-01-15' - DATE '2025-01-01' |
فرق الأيام | 14 |
NOW() + INTERVAL '30 days' |
إضافة فترة | بعد 30 يومًا |
NOW() - INTERVAL '1 year' |
طرح فترة | قبل سنة |
AGE(end, start) |
وصف الفترة | 1 year 2 mons 3 days |
AGE(timestamp) |
الفترة منذ الآن | — |
(11) ▶ مثال
SELECT
order_date,
order_date + 7 AS due_date,
CURRENT_DATE - order_date AS days_ago,
AGE(CURRENT_DATE, order_date) AS age_since_order
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '90 days';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(3) EXTRACT و DATE_TRUNC
| الاستخدام | المعنى | مثال | النتيجة |
|---|---|---|---|
EXTRACT(YEAR FROM ts) |
استخراج السنة | EXTRACT(YEAR FROM NOW()) |
2025 |
EXTRACT(MONTH FROM ts) |
استخراج الشهر | EXTRACT(MONTH FROM NOW()) |
6 |
EXTRACT(DAY FROM ts) |
استخراج اليوم | — | — |
EXTRACT(DOW FROM ts) |
يوم الأسبوع (0=الأحد) | — | 1 (الاثنين) |
EXTRACT(QUARTER FROM ts) |
ربع السنة | — | 2 |
EXTRACT(EPOCH FROM ts) |
طابع Unix الزمني | — | 1719500400 |
DATE_TRUNC('month', ts) |
اقتطاع إلى بداية الشهر | DATE_TRUNC('month', '2025-06-15') |
2025-06-01 |
DATE_TRUNC('year', ts) |
اقتطاع إلى بداية السنة | — | 2025-01-01 |
(12) ▶ مثال
SELECT
order_date,
EXTRACT(YEAR FROM order_date) AS order_year,
EXTRACT(MONTH FROM order_date) AS order_month,
EXTRACT(QUARTER FROM order_date) AS order_quarter,
EXTRACT(DOW FROM order_date) AS weekday
FROM orders
WHERE order_status = 'completed';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(13) ▶ مثال
SELECT
DATE_TRUNC('month', order_date) AS month_start,
COUNT(*) AS order_count,
SUM(total_amount) AS monthly_revenue
FROM orders
WHERE order_status = 'completed'
AND order_date >= DATE_TRUNC('year', CURRENT_DATE)
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month_start;
Output:
count
-------
5
(1 row)
(4) TO_CHAR و TO_DATE
| الدالة | الغرض | مثال |
|---|---|---|
TO_CHAR(ts, fmt) |
وقت → سلسلة | TO_CHAR(NOW(), 'YYYY-Month-DD') |
TO_DATE(s, fmt) |
سلسلة → تاريخ | TO_DATE('2025-06-15', 'YYYY-MM-DD') |
TO_TIMESTAMP(s, fmt) |
سلسلة → طابع زمني | TO_TIMESTAMP('2025-06-15 14:30', 'YYYY-MM-DD HH24:MI') |
قوالب التنسيق الشائعة:
| القالب | المعنى | مثال الإخراج |
|---|---|---|
YYYY |
سنة 4 أرقام | 2025 |
YY |
سنة رقمان | 25 |
Month |
اسم الشهر الكامل | June |
MON |
اسم الشهر المختصر | Jun |
MM |
شهر برقمين | 06 |
DD |
يوم برقمين | 15 |
HH24 |
24 ساعة | 14 |
MI |
دقيقة | 30 |
SS |
ثانية | 45 |
(14) ▶ مثال
SELECT
order_id,
TO_CHAR(order_date, 'YYYY-Month-DD') AS formatted_date,
TO_CHAR(order_date, 'YYYY-MM-DD HH24:MI:SS') AS full_datetime,
TO_CHAR(total_amount, 'FM$999,999.00') AS formatted_amount
FROM orders
WHERE order_status = 'completed';
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(15) ▶ مثال
SELECT
TO_DATE('2025-06-15', 'YYYY-MM-DD') AS parsed_date,
TO_DATE('15/06/2025', 'DD/MM/YYYY') AS eu_date,
TO_DATE('Jun 15 2025', 'Mon DD YYYY') AS us_date;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
6. المفهوم: الدوال الشرطية
(1) COALESCE
COALESCE(val1, val2, ...) يرجع أول وسيط غير NULL وهو أكثر دالة معالجة NULL شيوعًا.
| التعبير | النتيجة |
|---|---|
COALESCE(NULL, NULL, 'default') |
default |
COALESCE(100, 0) |
100 |
COALESCE(NULL, 0) |
0 |
(16) ▶ مثال
SELECT
product_name,
unit_price,
discount_rate,
COALESCE(discount_rate, 0) AS safe_discount,
unit_price * (1 - COALESCE(discount_rate, 0)) AS net_price
FROM products;
Output:
count
-------
5
(1 row)
(2) NULLIF
NULLIF(val1, val2) يرجع NULL عندما تتساوى القيمتان، وإلا يرجع val1. يستخدم عادة لتجنب أخطاء القسمة على صفر.
| التعبير | النتيجة |
|---|---|
NULLIF(100, 100) |
NULL |
NULLIF(100, 0) |
100 |
100 / NULLIF(0, 0) |
NULL (بدلاً من خطأ) |
(17) ▶ مثال
SELECT
product_name,
unit_price,
total_sold,
unit_price / NULLIF(total_sold, 0) AS revenue_per_unit
FROM products
WHERE is_active = true;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(3) GREATEST / LEAST
| الدالة | المعنى | مثال | النتيجة |
|---|---|---|---|
GREATEST(a, b, c) |
إرجاع القيمة القصوى | GREATEST(10, 20, 5) |
20 |
LEAST(a, b, c) |
إرجاع القيمة الدنيا | LEAST(10, 20, 5) |
5 |
(18) ▶ مثال
SELECT
product_name,
unit_price,
COALESCE(discount_rate, 0) AS discount,
unit_price * (1 - GREATEST(COALESCE(discount_rate, 0), 0.5)) AS capped_net_price,
LEAST(unit_price, 999.99) AS price_cap
FROM products
WHERE is_active = true;
Output:
count
-------
5
(1 row)
7. المفهوم: دوال التسلسل
(1) دوال عملية التسلسل
| الدالة | المعنى | مثال |
|---|---|---|
NEXTVAL('seq_name') |
زيادة وإرجاع القيمة التالية | NEXTVAL('order_id_seq') → 1001 |
CURRVAL('seq_name') |
إرجاع آخر NEXTVAL في الجلسة الحالية | CURRVAL('order_id_seq') → 1001 |
SETVAL('seq_name', n) |
تعيين القيمة الحالية للتسلسل | SETVAL('order_id_seq', 5000) |
SETVAL('seq_name', n, false) |
تعيين القيمة؛ NEXTVAL التالي يرجع n | SETVAL('order_id_seq', 5000, false) |
(19) ▶ مثال
INSERT INTO orders (order_id, customer_id, total_amount, order_date)
VALUES (NEXTVAL('order_id_seq'), 1001, 299.99, CURRENT_DATE);
Output:
INSERT 0 1
(20) ▶ مثال
SELECT
NEXTVAL('report_seq') AS report_number,
CURRVAL('report_seq') AS current_seq;
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
(2) SETVAL لإعادة تعيين تسلسل
| الاستدعاء | NEXTVAL التالي يرجع |
|---|---|
SETVAL('seq', 100) |
101 |
SETVAL('seq', 100, false) |
100 |
SETVAL('seq', 1, false) |
1 (إعادة تعيين إلى البداية) |
(21) ▶ مثال
-- إعادة تعيين التسلسل للبدء من 1 مرة أخرى
SELECT SETVAL('order_id_seq', 1, false);
-- تعيين التسلسل إلى قيمة عالية محددة (مثلاً، بعد ترحيل البيانات)
SELECT SETVAL('order_id_seq', (SELECT MAX(order_id) FROM orders));
Output:
id | name | value
----+----------+-------
1 | example | 42
(1 row)
8. مخطط التدفق: اختيار الدالة
flowchart TD
A[ما العملية التي تحتاجها؟] --> B{نوع البيانات؟}
B -->|رقمي| C{ماذا تحتاج؟}
B -->|سلسلة| D{ماذا تحتاج؟}
B -->|تاريخ| E{ماذا تحتاج؟}
B -->|معالجة NULL| F[COALESCE / NULLIF]
C -->|تقريب| G[ROUND / TRUNC]
C -->|تقريب إلى عدد صحيح| H[CEIL / FLOOR]
C -->|حساب| I[ABS / MOD / POWER / SQRT]
D -->|ربط| J[CONCAT / ||]
D -->|سلسلة جزئية| K[SUBSTRING / LEFT / RIGHT]
D -->|استبدال| L[REPLACE / SPLIT_PART]
D -->|حالة| M[LOWER / UPPER / INITCAP]
D -->|قص| N[TRIM / LTRIM / RTRIM]
E -->|وقت حالي| O[NOW / CURRENT_TIMESTAMP]
E -->|استخراج جزء| P[EXTRACT]
E -->|اقتطاع| Q[DATE_TRUNC]
E -->|تنسيق| R[TO_CHAR]
E -->|تحليل| S[TO_DATE / TO_TIMESTAMP]
style A fill:#e1f5fe
style F fill:#c8e6c9
9. مثال شامل
أنتجت Alice تقرير مبيعات شهري كامل.
-- الخطوة 1: تقرير إيرادات شهري مع تنسيق التاريخ
SELECT
TO_CHAR(DATE_TRUNC('month', order_date), 'YYYY-Month') AS report_month,
COUNT(*) AS order_count,
SUM(total_amount)::NUMERIC(12,2) AS gross_revenue,
SUM(total_amount * 0.08)::NUMERIC(12,2) AS tax_collected,
SUM(total_amount * 1.08)::NUMERIC(12,2) AS total_with_tax
FROM orders
WHERE order_status = 'completed'
AND order_date >= DATE_TRUNC('year', CURRENT_DATE)
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY report_month;
-- الخطوة 2: ملخص المنتجات مع تنسيق السلاسل ومعالجة NULL
SELECT
LPAD(p.product_id::TEXT, 6, '0') AS product_code,
INITCAP(LOWER(p.product_name)) AS display_name,
CONCAT('$', ROUND(p.unit_price, 2)) AS price_label,
COALESCE(p.discount_rate, 0) AS discount,
ROUND(p.unit_price * (1 - COALESCE(p.discount_rate, 0)), 2) AS net_price,
LEAST(ROUND(p.unit_price * (1 - COALESCE(p.discount_rate, 0)), 2), 999.99) AS capped_price
FROM products p
WHERE p.is_active = true
AND p.unit_price > NULLIF(p.cost_price, 0)
ORDER BY net_price DESC;
-- الخطوة 3: ملخص طلبات العملاء مع حساب العمر
SELECT
CONCAT(c.first_name, ' ', c.last_name) AS customer_name,
COUNT(o.order_id) AS total_orders,
SUM(o.total_amount)::NUMERIC(12,2) AS lifetime_value,
AGE(MAX(o.order_date), MIN(o.order_date)) AS customer_span,
EXTRACT(YEAR FROM AGE(CURRENT_DATE, c.register_date)) AS years_since_join
FROM customers c
JOIN orders o ON o.customer_id = c.customer_id
WHERE o.order_status = 'completed'
GROUP BY c.customer_id, c.first_name, c.last_name, c.register_date
ORDER BY lifetime_value DESC
FETCH FIRST 25 ROWS ONLY;
❓ أسئلة شائعة
||؟|| يرجع NULL للنتيجة الكاملة إذا كان أي معامل NULL. للربط الآمن مع NULL، استخدم CONCAT أو CONCAT_WS.DATE1 - DATE2 يرجع عددًا صحيحًا من الأيام؛ AGE(DATE1, DATE2) يرجع INTERVAL يشمل السنوات والأشهر والأيام (مثلاً، 1 year 2 mons 3 days) — أكثر ملاءمة للبشر، لكن أقل دقة من الطرح.📖 ملخص
- دوال الرياضيات:
ROUND/CEIL/FLOORللتقريب،ABS/MOD/POWER/SQRTللحساب؛ انتبه لقسمة الأعداد الصحيحة والدقة - دوال السلاسل:
CONCAT(آمن مع NULL) /||(غير آمن مع NULL)،SUBSTRING/LEFT/RIGHTللتقطيع،REPLACE/SPLIT_PARTللاستبدال/التقسيم - دوال التاريخ:
NOW/CURRENT_TIMESTAMPللوقت الحالي،EXTRACTلسحب الأجزاء،DATE_TRUNCللاقتطاع،TO_CHAR/TO_DATEللتنسيق والتحليل - الدوال الشرطية:
COALESCEيرجع أول غير NULL،NULLIFيرجع NULL عند التساوي لمنع القسمة على صفر،GREATEST/LEASTيأخذ القيم القصوى - دوال التسلسل:
NEXTVALيزيد ويرجع،CURRVALيقرأ القيمة الحالية،SETVALيعيد التعيين - دمج الدوال هو مهارة أساسية في العالم الواقعي — استخدم التداخل وتحويل الأنواع جيدًا
📝 تمارين
-
⭐ اكتب استعلامًا يختار
product_nameوunit_priceمنproducts، يستخدمCONCATلبناء تسمية سعر (تنسيق$99.99)، يستخدمROUNDللحفاظ على منزلتين عشريتين، ويرتب تنازليًا حسب السعر. -
⭐⭐ اكتب استعلامًا يولد تقرير مبيعات شهري لعام 2025: جمّع حسب الشهر بـ
DATE_TRUNC('month', order_date)، نسق الشهر بـTO_CHARكـYYYY-MM، احسب عدد الطلبات الشهري والمبلغ الإجمالي (NUMERIC(12,2)▶� واستخدمCOALESCEلمعالجة الخصومات NULL المحتملة. -
⭐⭐⭐ اكتب استعلامًا يولد صف تقرير لكل عميل: اربط الاسم بـ
CONCAT_WS، احسب مدة تسجيل العميل بـAGE، استخرج سنة التسجيل بـEXTRACT، حد الخصم عند 50% بـGREATEST، امنع القسمة على صفر عند حساب متوسط قيمة الطلب بـNULLIF، نسق معرف العميل كرقم من 6 أرقام بـLPAD، وأخيرًا ولد تسلسل صف التقرير بـNEXTVAL('report_seq').