Built-in funksiyalar — string, number, date, conditional

~20 daq · PostgreSQL · Funksiyalar va Protseduralar

Muammodan boshlaylik

Ma'lumot bazaga yoziladi — lekin har doim "toza" holda kelmaydi. Foydalanuvchi ismini " ali " bo'sh joylar bilan kiritdi. Telefon raqamini "+998 90 123 45 67" formatida yozdi, siz esa "998901234567" kerak. Sanani "2024-01-15" dan faqat yilni olmoqchisiz.

Bularning barchasini ilovada, kod yozib hal qilish mumkin. Lekin PostgreSQL o'zida yuzdan ortiq tayyor funksiya bor — ko'pini SQL so'rovning o'zida hal qilsa bo'ladi, kod tarafga yukmasa ham.

Bu darsda eng ko'p ishlatiladigan to'rtta guruh: matn, raqam, sana, shartli funksiyalar.


Matn funksiyalari

Bo'sh joylarni tozalash — TRIM

Foydalanuvchi kiritgan matnda boshida yoki oxirida bo'sh joy qolishi odatiy holat. TRIM — shu bo'sh joylarni olib tashlaydi.

SELECT TRIM('  ali karimov  ');    -- 'ali karimov'
SELECT LTRIM('  ali  ');           -- 'ali  '   (faqat chap)
SELECT RTRIM('  ali  ');           -- '  ali'   (faqat o'ng)

Foydalanuvchi ro'yxatdan o'tganda ismni tozalash:

INSERT INTO foydalanuvchilar (ism)
VALUES (TRIM('  Ali Karimov  '));
-- 'Ali Karimov' saqlanadi

Katta-kichik harf — UPPER, LOWER

Email manzillar katta-kichik harfga sezgir emas — lekin bazada ikki xil yozilishi mumkin: Ali@mail.com va ali@mail.com. Qidirishda muammo.

SELECT LOWER('Ali Karimov');   -- 'ali karimov'
SELECT UPPER('ali karimov');   -- 'ALI KARIMOV'

Email ni har doim kichik harfda saqlash:

INSERT INTO foydalanuvchilar (email)
VALUES (LOWER(TRIM('  Ali@Mail.Com  ')));
-- 'ali@mail.com' saqlanadi — har doim bir xil format

Uzunlik — LENGTH

SELECT LENGTH('Salom');         -- 5
SELECT LENGTH('');               -- 0
SELECT LENGTH(NULL);             -- NULL

Parol kamida 8 belgili bo'lishi kerakligini tekshirish:

SELECT * FROM foydalanuvchilar
WHERE LENGTH(parol) < 8;
-- Qisqa parollar

Kesish — SUBSTRING

Matnning bir qismini olish. Masalan, telefon raqamidan kodni ajratish:

SELECT SUBSTRING('998901234567', 1, 3);   -- '998'  (1-pozitsiyadan, 3 ta belgi)
SELECT SUBSTRING('998901234567' FROM 4);  -- '901234567' (4-pozitsiyadan oxirigacha)

Yoki regex bilan:

SELECT SUBSTRING('Narxi: 15000 so''m' FROM '[0-9]+');  -- '15000'

Almashtirish — REPLACE

Matn ichidagi bir narsani boshqasiga almashtirish:

SELECT REPLACE('901 234 56 78', ' ', '');   -- '901234567'  bo'shliqlar o'chirildi
SELECT REPLACE('ali@gmail.com', 'gmail', 'mail');  -- 'ali@mail.com'

Telefon raqamlarini standart formatga keltirish:

UPDATE foydalanuvchilar
SET telefon = REPLACE(REPLACE(telefon, ' ', ''), '-', '');
-- '90 123-45-67' → '901234567'

Birlashtirish — CONCAT va ||

SELECT CONCAT('Salom, ', 'Ali', '!');   -- 'Salom, Ali!'
SELECT 'Salom, ' || 'Ali' || '!';       -- 'Salom, Ali!'  (bir xil)

-- CONCAT NULL ni e'tiborsiz qoldiradi
SELECT CONCAT('Salom, ', NULL, 'Ali');  -- 'Salom, Ali'

-- || esa NULL bilan NULL qaytaradi
SELECT 'Salom, ' || NULL || 'Ali';      -- NULL

Bu farq muhim: foydalanuvchining familiya ustuni NULL bo'lishi mumkin bo'lsa — || ishlatilsa butun natija NULL bo'ladi.

-- ✅ — familiya NULL bo'lsa ham ishlaydi
SELECT CONCAT(ism, ' ', familiya) AS toʻliq_ism FROM foydalanuvchilar;

-- ❌ — familiya NULL bo'lsa toʻliq_ism ham NULL
SELECT ism || ' ' || familiya AS toʻliq_ism FROM foydalanuvchilar;

Boshqa foydali matn funksiyalari

SELECT LEFT('Salom dunyo', 5);     -- 'Salom'  (chapdan 5 ta)
SELECT RIGHT('Salom dunyo', 5);    -- 'dunyo'  (o'ngdan 5 ta)
SELECT REVERSE('Salom');           -- 'molaS'
SELECT REPEAT('ab', 3);            -- 'ababab'
SELECT LPAD('42', 5, '0');         -- '00042'  (chapga 0 bilan to'ldirish)
SELECT RPAD('42', 5, '0');         -- '42000'  (o'ngga 0 bilan to'ldirish)
SELECT POSITION('ali' IN 'salom ali');  -- 7  (qaysi pozitsiyada)

Raqam funksiyalari

Yaxlitlash — ROUND, CEIL, FLOOR

Uch xil yaxlitlash usuli bor — qaysi birini tanlash vaziyatga bog'liq.

SELECT ROUND(4.6);    -- 5    (eng yaqin butun)
SELECT ROUND(4.4);    -- 4    (eng yaqin butun)
SELECT ROUND(4.567, 2); -- 4.57  (ikki kasr)

SELECT CEIL(4.1);     -- 5    (yuqoriga — har doim kattaroq butun)
SELECT CEIL(4.9);     -- 5

SELECT FLOOR(4.9);    -- 4    (pastga — har doim kichikroq butun)
SELECT FLOOR(4.1);    -- 4

Narxni hisoblashda: soliq qo'shilganda har doim yuqoriga yaxlitlash (CEIL), chegirma berganada pastga (FLOOR).


Absolut qiymat, qoldiq, daraja

SELECT ABS(-15);          -- 15    (manfiy bo'lsa ham musbat)
SELECT MOD(17, 5);        -- 2     (17 ni 5 ga bo'lganda qoldiq)
SELECT POWER(2, 10);      -- 1024  (2 ning 10-darajasi)
SELECT SQRT(144);         -- 12    (kvadrat ildiz)

Tasodifiy raqam — RANDOM

SELECT RANDOM();                    -- 0 va 1 orasida: 0.7341...
SELECT FLOOR(RANDOM() * 100) + 1;  -- 1 dan 100 gacha tasodifiy butun

Sana va vaqt funksiyalari

Hozirgi vaqt

SELECT NOW();              -- 2024-04-15 14:23:45.123456+05
SELECT CURRENT_DATE;       -- 2024-04-15  (faqat sana)
SELECT CURRENT_TIME;       -- 14:23:45.123456+05  (faqat vaqt)

NOW() — tranzaksiya boshlanganidagi vaqt. CLOCK_TIMESTAMP() — har chaqirilganda haqiqiy joriy vaqt.


Sanadan qism ajratish — EXTRACT va DATE_PART

SELECT EXTRACT(YEAR  FROM NOW());   -- 2024
SELECT EXTRACT(MONTH FROM NOW());   -- 4
SELECT EXTRACT(DAY   FROM NOW());   -- 15
SELECT EXTRACT(DOW   FROM NOW());   -- 1  (haftaning kuni: 0=yakshanba, 1=dushanba)
SELECT EXTRACT(HOUR  FROM NOW());   -- 14

Oylik hisobot uchun — faqat oy bo'yicha filtrlash:

SELECT * FROM buyurtmalar
WHERE EXTRACT(YEAR FROM sana) = 2024
  AND EXTRACT(MONTH FROM sana) = 4;

Sana formatlash — TO_CHAR

Sanani istalgan formatda matn sifatida chiqarish:

SELECT TO_CHAR(NOW(), 'DD.MM.YYYY');          -- '15.04.2024'
SELECT TO_CHAR(NOW(), 'DD-Mon-YYYY');         -- '15-Apr-2024'
SELECT TO_CHAR(NOW(), 'HH24:MI:SS');          -- '14:23:45'
SELECT TO_CHAR(NOW(), 'DD.MM.YYYY HH24:MI'); -- '15.04.2024 14:23'

Raqamni formatlash:

SELECT TO_CHAR(1234567.89, '9,999,999.99');  -- '1,234,567.89'
SELECT TO_CHAR(0.15, 'FM99%');               -- '15%'

Sana hisoblash — vaqt oralig'i

-- 30 kun qo'shish
SELECT NOW() + INTERVAL '30 days';

-- 1 oy oldin
SELECT NOW() - INTERVAL '1 month';

-- Ikkita sana orasidagi kunlar
SELECT ('2024-12-31'::DATE - '2024-01-01'::DATE);  -- 365

-- Yoshni hisoblash
SELECT EXTRACT(YEAR FROM AGE('1995-06-15'));  -- 29 (2024 yilga qarab)

Obuna tugash sanasini hisoblash:

UPDATE foydalanuvchilar
SET obuna_tugash = NOW() + INTERVAL '1 year'
WHERE id = 1;

Shartli funksiyalar

COALESCE — birinchi NULL bo'lmagan qiymat

COALESCE — ro'yxatdan birinchi NULL bo'lmagan qiymatni qaytaradi. NULL o'rniga standart qiymat ko'rsatishda eng ko'p ishlatiladigan funksiya.

SELECT COALESCE(NULL, NULL, 'standart');   -- 'standart'
SELECT COALESCE(NULL, 'ikkinchi', 'uchinchi'); -- 'ikkinchi'
SELECT COALESCE('birinchi', 'ikkinchi');   -- 'birinchi'

Amalda — foydalanuvchi ismi yo'q bo'lsa "Anonim" ko'rsatish:

SELECT COALESCE(ism, 'Anonim') AS koʻrinish
FROM foydalanuvchilar;
 koʻrinish
-----------
 Ali
 Anonim     ← ism NULL edi
 Vali

NULLIF — ikki qiymat teng bo'lsa NULL qaytarish

NULLIF(a, b) — agar a = b bo'lsa NULL, aks holda a qaytaradi. Nolga bo'lish xatosini oldini olishda foydali:

SELECT 100 / NULLIF(0, 0);    -- NULL  (0 ga bo'lish o'rniga NULL)
SELECT 100 / NULLIF(5, 0);    -- 20

Bo'sh satr o'rniga NULL saqlash:

UPDATE foydalanuvchilar
SET telefon = NULLIF(TRIM(telefon), '');
-- '  ' → NULL, '901234567' → '901234567'

CASE — shartli ifoda

SQL dagi if/else. Natijani shartga qarab o'zgartirish:

SELECT
  nomi,
  narx,
  CASE
    WHEN narx < 500000   THEN 'Arzon'
    WHEN narx < 2000000  THEN 'O''rta'
    ELSE                      'Qimmat'
  END AS toifa
FROM mahsulotlar;
   nomi      │   narx    │  toifa
-------------+-----------+---------
 Sichqon     │   150 000 │ Arzon
 Klaviatura  │   350 000 │ Arzon
 Headset     │   450 000 │ Arzon
 Noutbuk     │ 5 000 000 │ Qimmat
 Monitor     │ 2 800 000 │ Qimmat

Qisqa shakl — bitta ustunni tekshirish:

SELECT holat,
  CASE holat
    WHEN 'pending'    THEN 'Kutilmoqda'
    WHEN 'processing' THEN 'Jarayonda'
    WHEN 'delivered'  THEN 'Yetkazildi'
    ELSE                   'Boshqa'
  END AS holat_uz
FROM buyurtmalar;

Tez-tez uchraydigan xatolar

|| bilan NULL qo'shish:

-- ❌ — familiya NULL bo'lsa natija NULL
SELECT ism || ' ' || familiya FROM foydalanuvchilar;

-- ✅ — COALESCE bilan NULL ni bo'sh satrga aylantirish
SELECT ism || ' ' || COALESCE(familiya, '') FROM foydalanuvchilar;
-- Yoki CONCAT — NULL ni avtomatik e'tiborsiz qoldiradi
SELECT CONCAT(ism, ' ', familiya) FROM foydalanuvchilar;

Sana filtrlashda indeksni buzish:

-- ❌ — EXTRACT hisoblash kerak, indeks ishlamaydi
WHERE EXTRACT(YEAR FROM sana) = 2024;

-- ✅ — to'g'ridan-to'g'ri sana oralig'i, indeks ishlaydi
WHERE sana >= '2024-01-01' AND sana < '2025-01-01';

EXTRACT va TO_CHAR funksiyalar sana ustunini o'zgartiradi — indeks esa asl ustun bo'yicha qurilgan, shu sababli ishlatilmaydi. Sana oralig'i bilan filtr — aniqroq va tezroq.


Xulosa

PostgreSQL built-in funksiyalari ma'lumotni bazaning o'zida tozalash, formatlash, hisoblash imkonini beradi.

Matn:    TRIM, LOWER/UPPER, LENGTH, SUBSTRING, REPLACE, CONCAT
Raqam:   ROUND, CEIL, FLOOR, ABS, MOD, POWER
Sana:    NOW, EXTRACT, TO_CHAR, AGE, INTERVAL
Shartli: COALESCE, NULLIF, CASE

Bir qoida esda tuting: funksiyani WHERE da ustun ustida ishlatish indeksni o'chiradi. Mumkin bo'lsa, ustunni o'zgartirmay, qiymatni o'zgartiring — yoki generated column ishlating.


Keyingi dars

31-dars: PL/pgSQL — asoslar, o'zgaruvchilar, shartlar, sikllar