10 β Built-in funksiyalar (matn, son, sana)¶
β¬ οΈ Oldingi: 09 β ORDER BY, LIMIT, DISTINCT Β· π README Β· Keyingi: 11 β Aggregate funksiyalar va GROUP BY β‘οΈ
Bu bobda: MySQL'ning tayyor (built-in) funksiyalari bilan tanishamiz: matnni o'zgartirish (UPPER, CONCAT, SUBSTRING, REPLACE), sonlarni yaxlitlash (ROUND, CEIL, FLOOR), sana hisob-kitoblari (NOW, DATEDIFF, DATE_FORMAT, TIMESTAMPDIFF), shartga qarab qiymat tanlash (IF, CASE) va NULL bilan ishlash (IFNULL, COALESCE)ni o'rganamiz.
MySQL'da yuzlab tayyor funksiya bor. Ularni kalkulyatordagi tugmalar deb tasavvur qiling: kvadrat ildizni qog'ozda hisoblab o'tirmaysiz β tayyor tugmani bosasiz. SQL funksiyasi ham xuddi shunday ishlaydi: unga qiymat berasiz, u amalni bajarib, natijani qaytaradi. Hammasini yodlash shart emas β bu bobda eng ko'p ishlatiladiganlarini ko'ramiz, qolganini kerak bo'lganda hujjatdan qarab olasiz.
π Eng muhim qoida: bu funksiyalar jadvaldagi asl ma'lumotni o'zgartirmaydi. Ular faqat SELECT natijasi qanday ko'rinishini belgilaydi: SELECT UPPER(nomi) ... deb yozsangiz ham, jadvalda nomi avvalgidek o'z holicha qolaveradi. (Ma'lumotni haqiqatan o'zgartirish β UPDATE, uni 17-bobda ko'ramiz.)
Matn funksiyalari¶
SELECT UPPER('salom'); -- SALOM (katta harfga)
SELECT LOWER('SALOM'); -- salom (kichik harfga)
SELECT LENGTH('salom'); -- 5 (BAYTlarda o'lchaydi)
SELECT CHAR_LENGTH('salom'); -- 5 (BELGIlarda o'lchaydi)
SELECT CONCAT('Aziz', ' ', 'Karimov'); -- Aziz Karimov (matnlarni ulaydi)
SELECT SUBSTRING('Salom dunyo', 1, 5); -- Salom (1-belgidan boshlab 5 ta)
SELECT REPLACE('+998901112233', '+998', ''); -- 901112233 (almashtiradi)
SELECT TRIM(' salom '); -- salom (chetdagi bo'shliqlar ketadi)
SELECT LEFT('Salom', 3); -- Sal (boshidan 3 ta)
SELECT RIGHT('Salom', 3); -- lom (oxiridan 3 ta)
LENGTH va CHAR_LENGTH β qachon farq qiladi? Lotin harflarida ikkalasi bir xil son beradi, chunki har lotin harfi 1 bayt joy oladi. Lekin kirill va boshqa "keng" belgilar bir necha bayt egallaydi:
SELECT LENGTH('Π’ΠΎΡΠΊΠ΅Π½Ρ'); -- 14 (har kirill harfi 2 bayt)
SELECT CHAR_LENGTH('Π’ΠΎΡΠΊΠ΅Π½Ρ'); -- 7 (harflar soni)
Xulosa oddiy: "necha ta harf?" degan savolga doim CHAR_LENGTH to'g'ri javob beradi.
SUBSTRING 1 dan sanaydi. Ko'p dasturlash tillarida sanash 0 dan boshlanadi, SQL'da esa 1 dan: birinchi belgi β 1-pozitsiya. Uchinchi argumentni yozmasangiz, oxirigacha olib beradi:
CONCAT'ning NULL tuzog'i. Argumentlardan bittasi NULL bo'lsa, butun natija NULL bo'lib qoladi. Bunday holatda CONCAT_WS (WS β "with separator", ya'ni ajratuvchi bilan) qutqaradi: birinchi argument ajratuvchi bo'ladi, NULL'larni esa shunchaki tashlab ketadi:
SELECT CONCAT('Aziz', NULL, 'Karimov'); -- NULL!
SELECT CONCAT_WS(' ', 'Aziz', NULL, 'Karimov'); -- Aziz Karimov
Funksiyalarni ichma-ich yozish ham mumkin β MySQL ularni ichkaridan tashqariga qarab hisoblaydi:
Son funksiyalari¶
SELECT ROUND(4.567, 2); -- 4.57 (2 xonagacha yaxlitlaydi)
SELECT ROUND(4.567); -- 5 (butun songa yaxlitlaydi)
SELECT TRUNCATE(4.567, 2); -- 4.56 (yaxlitlamaydi, shunchaki kesadi)
SELECT CEIL(4.1); -- 5 (doim yuqoriga)
SELECT FLOOR(4.9); -- 4 (doim pastga)
SELECT ABS(-15); -- 15 (modul β ishorani tashlaydi)
SELECT MOD(10, 3); -- 1 (bo'lishdan qolgan qoldiq; 10 % 3 ham shu)
SELECT POW(2, 10); -- 1024 (daraja: 2 ning 10-darajasi)
SELECT RAND(); -- 0 va 1 orasida tasodifiy son (har safar boshqa)
ROUND va TRUNCATE farqiga e'tibor bering: ROUND matematik qoida bo'yicha yaxlitlaydi (4.567 β 4.57), TRUNCATE esa ortiqcha xonalarni shunchaki uzib tashlaydi (4.567 β 4.56). Pul hisob-kitoblarida bu kichik farq katta ahamiyatga ega bo'lishi mumkin!
Sana funksiyalari¶
Sanalar bilan ishlash β real loyihalardagi eng ko'p uchraydigan vazifalardan biri: "necha kun o'tdi?", "muddat qachon tugaydi?", "mijoz necha yoshda?". MySQL bunga boy asboblar to'plamini beradi:
SELECT NOW(); -- hozirgi sana+vaqt (DATETIME)
SELECT CURDATE(); -- bugungi sana (faqat DATE)
SELECT YEAR('2026-06-09'); -- 2026
SELECT MONTH('2026-06-09'); -- 6
SELECT DAY('2026-06-09'); -- 9
SELECT HOUR('2026-06-09 18:45:00'); -- 18 (MINUTE va SECOND ham bor)
SELECT DAYNAME('2026-06-09'); -- Tuesday (seshanba)
SELECT DATEDIFF('2026-06-09', '2026-05-01'); -- 39 (ikki sana orasidagi kunlar)
SELECT DATE_ADD('2026-06-09', INTERVAL 15 DAY); -- 2026-06-24 (15 kun keyin)
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH); -- 1 oy oldin
SELECT DATE_FORMAT(NOW(), '%d.%m.%Y'); -- masalan: 09.06.2026
SELECT TIMESTAMPDIFF(YEAR, '1990-08-25', CURDATE()); -- yosh hisoblash!
π DAYNAME (va MONTHNAME) natijani inglizcha qaytaradi. Tilni lc_time_names sozlamasi bilan o'zgartirsa bo'ladi (masalan, SET lc_time_names = 'ru_RU';), lekin o'zbekcha lokal MySQL'da yo'q β kerak bo'lsa CASE bilan o'zingiz tarjima qilasiz.
DATE_FORMAT kodlari. Eng ko'p ishlatiladiganlari:
| Kod | Ma'nosi | Misol |
|---|---|---|
%d |
kun (2 xonali) | 09 |
%m |
oy (2 xonali) | 06 |
%Y |
yil (4 xonali) | 2026 |
%H |
soat (24 soatlik) | 18 |
%i |
minut | 05 |
%s |
sekund | 30 |
%W |
hafta kuni nomi | Tuesday |
%M |
oy nomi | June |
β οΈ Klassik tuzoq: minut β %i, %m emas (%m β oy!). %M esa umuman boshqa narsa β oy nomi. Katta-kichik harf farqiga diqqat qiling.
Yosh hisoblashda TIMESTAMPDIFF ishonchli. "Yillarni bir-biridan ayirib qo'ya qolaman" desangiz, xato chiqishi mumkin:
-- Bugun 2026-06-10 deb olaylik. 1990-08-25 da tug'ilgan odam:
SELECT TIMESTAMPDIFF(YEAR, '1990-08-25', '2026-06-10'); -- 35 (to'g'ri: avgust hali kelmadi)
SELECT YEAR('2026-06-10') - YEAR('1990-08-25'); -- 36 (xato: 1 yosh oshirib yubordi)
TIMESTAMPDIFF faqat to'liq o'tgan yillarni sanaydi β xuddi hayotdagidek: odam tug'ilgan kunigacha hali 35 yoshda, 36 emas.
IF va CASE β shartli qiymat¶
Ba'zan natija ustunini shartga qarab hosil qilish kerak: omborda mahsulot "bor"mi yoki "tugagan"mi? IF funksiyasi uch qism oladi β IF(shart, rost bo'lsa shu, yolg'on bo'lsa bu):
Shartlar ikkitadan ko'p bo'lsa, CASE ishlatamiz. U shartlarni yuqoridan pastga tekshiradi va birinchi mos kelganida to'xtaydi β shuning uchun eng kichik chegara birinchi turibdi. ELSE esa "hech biri mos kelmasa" bo'limi:
SELECT nomi, narx,
CASE
WHEN narx < 1000000 THEN 'arzon'
WHEN narx < 10000000 THEN 'ortacha'
ELSE 'qimmat'
END AS toifa
FROM dokon.mahsulotlar;
π‘ IF() β MySQL'ga xos funksiya, CASE esa SQL standarti: PostgreSQL, SQLite va boshqa bazalarda ham aynan shunday ishlaydi. Shart ikkitadan ko'p bo'lsa yoki kod boshqa bazaga ko'chishi mumkin bo'lsa β CASE'ni tanlang.
NULL bilan ishlash funksiyalari¶
8-bobdan eslang: NULL β "qiymat yo'q" degani va u bilan oddiy taqqoslash ishlamaydi. Natijada NULL o'rniga tushunarli matn ko'rsatish uchun ikkita funksiya bor:
SELECT ism, IFNULL(telefon, 'telefon yoq') FROM kutubxona.azolar;
SELECT COALESCE(NULL, NULL, 'birinchi NULL bolmagan', 'x'); -- 3-qiymat qaytadi
- IFNULL(a, b) β ikki argument:
aNULL bo'lmasaani, NULL bo'lsabni qaytaradi. - COALESCE(...) β istalgancha argument: chapdan boshlab birinchi NULL bo'lmagan qiymatni qaytaradi. "Ish telefoni bo'lsa β shuni, bo'lmasa uy telefonini, u ham bo'lmasa 'aloqa yoq' deb ko'rsat" kabi mantiq uchun juda qulay.
π‘ Funksiyalarni WHERE ichida ham bemalol ishlatish mumkin:
Lekin bilib qo'ying: katta jadvalda ustunga funksiya qo'llab filtrlash qidiruvni sekinlashtirishi mumkin β bunga 21-bobda (indekslar) qaytamiz.
10-bob masalalari¶
- (kutubxona) Kitob nomlarini KATTA harflarda chiqaring
- (kutubxona) Har kitob nomining uzunligini chiqaring (CHAR_LENGTH)
- (kutubxona) Muallif ismi va davlatini bitta ustunda: 'Abdulla Qodiriy (Ozbekiston)' β CONCAT
- (kutubxona) A'zolar telefonidan '+998' ni olib tashlab ko'rsating (REPLACE)
- (kutubxona) Har kitob necha yoshda:
2026 - yilyoki YEAR(CURDATE()) - yil - (kutubxona) Ijara necha kun davom etgan: DATEDIFF(qaytarilgan_sana, olingan_sana) β qaytarilganlar uchun
- (kutubxona) Qaytarilmagan kitoblar bugungacha necha kundan beri o'qilmoqda: DATEDIFF(CURDATE(), olingan_sana)
- (kutubxona) Har ijara uchun "muddat": 15 kundan oshsa 'kechikkan', aks holda 'normal' (IF + DATEDIFF)
- (dokon) Narxlarni yaxlitlab ming so'mda: ROUND(narx/1000) AS ming_som
- (dokon) Mahsulot holati CASE bilan: soni=0 β 'tugagan', soni<10 β 'oz qoldi', aks holda 'yetarli'
- (dokon) Mahsulot nomining birinchi 10 belgisi + '...' (LEFT va CONCAT)
- (dokon) Buyurtma sanasini '09.06.2026 18:00' formatida (DATE_FORMAT: '%d.%m.%Y %H:%i')
- (dokon) Har buyurtma qaysi hafta kuni qilinganini chiqaring (DAYNAME)
- (klinika) Har bemorning yoshini hisoblang (TIMESTAMPDIFF)
- (klinika) Bemor ismini 'LOLA MIRZAYEVA' ko'rinishida (UPPER)
- (klinika) Telefoni NULL bo'lsa 'korsatilmagan' deb chiqaring (IFNULL)
- (klinika) Yosh toifasi CASE bilan: <18 'bola', 18-60 'katta', >60 'keksa'
- (taksi) Narxni 500 ga yaxlitlang: ROUND(narx/500)*500 β sinab ko'ring va nega aynan shunday yozilishini tushunib oling
- (taksi) Har safarning km narxini 2 xona aniqlikda: ROUND(narx/masofa_km, 2)
- (taksi) Safar sanasidan faqat soatni chiqaring (HOUR funksiyasi); 18:00 dan keyingilarga 'kechki', oldingilariga 'kunduzgi' deb belgi qo'ying