17-bo‘lim
VIEW, protsedura va triggerlar
Ko'rinishlar (VIEW), saqlanuvchi protseduralar va funksiyalar, triggerlar va hodisalar (events).
Ushbu bo‘lim mundarijasi
Bu bo'limda SQL ni qayta ishlatiladigan qilish vositalarini ko'ramiz.
VIEW - ko'rinish #
VIEW - nomlangan so'rov. U jadval kabi ishlatiladi, lekin ma'lumot saqlamaydi.
CREATE VIEW talaba_royxati AS
SELECT
t.id,
CONCAT(t.ism, ' ', t.familiya) AS toliq_ism,
t.email,
t.shahar,
t.ortacha_baho,
g.nomi AS guruh
FROM talabalar t
LEFT JOIN guruhlar g ON g.id = t.guruh_id
WHERE t.faolmi = TRUE;
Endi uni oddiy jadval kabi ishlatamiz:
SELECT * FROM talaba_royxati WHERE shahar = 'Toshkent';
SELECT guruh, COUNT(*) FROM talaba_royxati GROUP BY guruh;
| Buyruq | Vazifasi |
|---|---|
CREATE VIEW nom AS ... | Yaratish |
CREATE OR REPLACE VIEW | Yaratish yoki almashtirish |
SHOW CREATE VIEW nom | Ta'rifini ko'rish |
DROP VIEW nom | O'chirish |
SHOW FULL TABLES WHERE Table_type = 'VIEW' | Ro'yxat |
| Foyda | Izoh |
|---|---|
| Murakkablikni yashiradi | 5 jadvalli JOIN bitta nom ostida |
| Qayta ishlatish | Bir so'rovni o'nlab joyda |
| Xavfsizlik | Foydalanuvchiga faqat kerakli ustunlarni ochish |
| Moslik | Jadval o'zgarsa, VIEW eski interfeysni saqlaydi |
Xavfsizlik uchun VIEW #
-- Maosh ustunini yashiramiz
CREATE VIEW xodimlar_ochiq AS
SELECT id, ism, lavozim, bolim
FROM xodimlar;
-- Foydalanuvchiga faqat VIEW ga ruxsat beramiz
GRANT SELECT ON kompaniya.xodimlar_ochiq TO 'oddiy_xodim'@'localhost';
Foydalanuvchi maosh ustunini umuman ko'ra olmaydi.
VIEW cheklovlari #
- Ma'lumot saqlamaydi - har safar asosiy so'rov qayta bajariladi.
- Indeks yaratib bo'lmaydi - MySQL da materiallashgan VIEW yo'q.
- Ba'zilarini o'zgartirib bo'lmaydi -
GROUP BY,DISTINCT,JOINbo'lsaINSERT/UPDATEishlamaydi. - Ichma-ich VIEW sekin - VIEW ichida VIEW ishlatishdan qoching.
Agar sekin so'rovni tezlashtirish kerak bo'lsa, VIEW yordam bermaydi - u shunchaki nom, optimizatsiya emas.
-- O'zgartirish mumkin bo'lgan VIEW
CREATE VIEW faol_talabalar AS
SELECT id, ism, familiya, email, faolmi
FROM talabalar
WHERE faolmi = TRUE
WITH CHECK OPTION;
UPDATE faol_talabalar SET ism = 'Yangi' WHERE id = 1; -- ishlaydi
WITH CHECK OPTION - VIEW shartini buzadigan o'zgarishga yo'l qo'ymaydi.
Saqlanuvchi protseduralar #
Protsedura - bazada saqlanadigan SQL kodi.
DELIMITER //
CREATE PROCEDURE guruh_statistikasi(IN p_guruh_id INT UNSIGNED)
BEGIN
SELECT
g.nomi AS guruh,
COUNT(t.id) AS talabalar,
ROUND(AVG(t.ortacha_baho), 2) AS ortacha,
MAX(t.ortacha_baho) AS eng_yuqori
FROM guruhlar g
LEFT JOIN talabalar t ON t.guruh_id = g.id
WHERE g.id = p_guruh_id
GROUP BY g.id, g.nomi;
END //
DELIMITER ;
CALL guruh_statistikasi(1);
DELIMITER nima uchun kerak?Protsedura ichida ; belgisi bor. MySQL uni "buyruq tugadi" deb tushunadi va
protsedurani yarim yo'lda kesib qo'yadi.
DELIMITER // buyruq oxiri belgisini vaqtincha // ga o'zgartiradi.
Protsedura yozib bo'lingach, DELIMITER ; bilan qaytariladi.
Parametr turlari #
DELIMITER //
CREATE PROCEDURE pul_otkazish(
IN p_kimdan INT UNSIGNED,
IN p_kimga INT UNSIGNED,
IN p_summa DECIMAL(12,2),
OUT p_natija VARCHAR(100)
)
BEGIN
DECLARE v_balans DECIMAL(12,2);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET p_natija = 'Xatolik yuz berdi';
END;
START TRANSACTION;
SELECT balans INTO v_balans
FROM hisoblar WHERE id = p_kimdan FOR UPDATE;
IF v_balans < p_summa THEN
SET p_natija = 'Mablag'' yetarli emas';
ROLLBACK;
ELSE
UPDATE hisoblar SET balans = balans - p_summa WHERE id = p_kimdan;
UPDATE hisoblar SET balans = balans + p_summa WHERE id = p_kimga;
SET p_natija = 'Muvaffaqiyatli';
COMMIT;
END IF;
END //
DELIMITER ;
CALL pul_otkazish(1, 2, 500000, @natija);
SELECT @natija;
| Tur | Ma'nosi |
|---|---|
IN | Kiruvchi parametr (standart) |
OUT | Chiquvchi natija |
INOUT | Ikkalasi |
Saqlanuvchi funksiyalar #
Funksiya qiymat qaytaradi va so'rov ichida ishlatiladi:
DELIMITER //
CREATE FUNCTION harfli_baho(p_baho DECIMAL(3,2))
RETURNS VARCHAR(20)
DETERMINISTIC
READS SQL DATA
BEGIN
IF p_baho >= 4.5 THEN RETURN 'A''lo';
ELSEIF p_baho >= 3.5 THEN RETURN 'Yaxshi';
ELSEIF p_baho >= 3.0 THEN RETURN 'Qoniqarli';
ELSE RETURN 'Qoniqarsiz';
END IF;
END //
DELIMITER ;
SELECT ism, ortacha_baho, harfli_baho(ortacha_baho) AS daraja
FROM talabalar;
+----------+--------------+-----------+
| ism | ortacha_baho | daraja |
+----------+--------------+-----------+
| Husanboy | 4.60 | A'lo |
| Sardor | 3.80 | Yaxshi |
| Bekzod | 3.20 | Qoniqarli |
+----------+--------------+-----------+
| Belgi | Ma'nosi |
|---|---|
DETERMINISTIC | Bir xil kirish - bir xil natija |
READS SQL DATA | Faqat o'qiydi |
MODIFIES SQL DATA | Ma'lumotni o'zgartiradi |
NO SQL | SQL ishlatmaydi |
SELECT * FROM talabalar WHERE harfli_baho(ortacha_baho) = 'A''lo';
Bu har bir qator uchun funksiyani chaqiradi va indeksni buzadi.
WHERE da funksiya ishlatmang - shartni to'g'ridan-to'g'ri yozing:
WHERE ortacha_baho >= 4.5
Boshqaruv konstruksiyalari #
DELIMITER //
CREATE PROCEDURE misol()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE v_natija VARCHAR(200) DEFAULT '';
-- IF
IF i > 0 THEN
SET v_natija = 'musbat';
ELSEIF i = 0 THEN
SET v_natija = 'nol';
ELSE
SET v_natija = 'manfiy';
END IF;
-- CASE
CASE i
WHEN 1 THEN SET v_natija = 'bir';
WHEN 2 THEN SET v_natija = 'ikki';
ELSE SET v_natija = 'boshqa';
END CASE;
-- WHILE
SET i = 1;
WHILE i <= 5 DO
SET v_natija = CONCAT(v_natija, i, ' ');
SET i = i + 1;
END WHILE;
-- REPEAT
SET i = 1;
REPEAT
SET i = i + 1;
UNTIL i > 5
END REPEAT;
SELECT v_natija;
END //
DELIMITER ;
Triggerlar #
Trigger - ma'lum hodisadan oldin yoki keyin avtomatik ishga tushadigan kod.
DELIMITER //
-- Talaba qo'shilganda guruh hisoblagichini oshirish
CREATE TRIGGER talaba_qoshildi
AFTER INSERT ON talabalar
FOR EACH ROW
BEGIN
UPDATE guruhlar
SET talabalar_soni = talabalar_soni + 1
WHERE id = NEW.guruh_id;
END //
-- Talaba o'chirilganda kamaytirish
CREATE TRIGGER talaba_ochirildi
AFTER DELETE ON talabalar
FOR EACH ROW
BEGIN
UPDATE guruhlar
SET talabalar_soni = talabalar_soni - 1
WHERE id = OLD.guruh_id;
END //
DELIMITER ;
| Kalit so'z | Ma'nosi |
|---|---|
BEFORE / AFTER | Hodisadan oldin / keyin |
INSERT / UPDATE / DELETE | Qaysi hodisa |
NEW.ustun | Yangi qiymat (INSERT, UPDATE) |
OLD.ustun | Eski qiymat (UPDATE, DELETE) |
Amaliy triggerlar #
DELIMITER //
-- 1. Ma'lumotni tekshirish
CREATE TRIGGER baho_tekshiruvi
BEFORE INSERT ON talabalar
FOR EACH ROW
BEGIN
IF NEW.ortacha_baho < 0 OR NEW.ortacha_baho > 5 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Baho 0 va 5 orasida bo''lishi kerak';
END IF;
SET NEW.email = LOWER(TRIM(NEW.email)); -- normalizatsiya
END //
-- 2. O'zgarishlar tarixini yozish (audit)
CREATE TRIGGER narx_ozgarishi
AFTER UPDATE ON mahsulotlar
FOR EACH ROW
BEGIN
IF OLD.narx <> NEW.narx THEN
INSERT INTO narx_tarixi (mahsulot_id, eski_narx, yangi_narx, ozgartirilgan)
VALUES (NEW.id, OLD.narx, NEW.narx, NOW());
END IF;
END //
-- 3. Yumshoq o'chirishni majburlash
CREATE TRIGGER ochirishni_taqiqlash
BEFORE DELETE ON mijozlar
FOR EACH ROW
BEGIN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Mijozni o''chirib bo''lmaydi. faolmi = FALSE qiling.';
END //
DELIMITER ;
| Muammo | Izoh |
|---|---|
| Ko'rinmaydi | Kodni o'qiganda trigger borligi bilinmaydi |
| Nosozlikni tuzatish qiyin | "Nima uchun bu qiymat o'zgardi?" |
| Sekinlashtiradi | Har bir INSERT qo'shimcha ish qiladi |
| Zanjir hosil qiladi | Trigger boshqa triggerni ishga tushiradi |
Tavsiya: mantiqni imkon qadar dastur kodida yozing. Triggerlarni faqat audit (o'zgarishlar tarixi) va qat'iy cheklovlar uchun ishlating.
SHOW TRIGGERS;
DROP TRIGGER IF EXISTS talaba_qoshildi;
Hodisalar (events) #
Rejalashtirilgan avtomatik vazifalar:
SET GLOBAL event_scheduler = ON;
DELIMITER //
-- Har kuni yarim tunda eski loglarni tozalash
CREATE EVENT loglarni_tozalash
ON SCHEDULE EVERY 1 DAY
STARTS '2026-09-10 00:00:00'
DO
BEGIN
DELETE FROM loglar
WHERE yaratilgan < DATE_SUB(NOW(), INTERVAL 90 DAY);
END //
-- Har soatda statistikani yangilash
CREATE EVENT statistikani_yangilash
ON SCHEDULE EVERY 1 HOUR
DO
BEGIN
REPLACE INTO kunlik_statistika (sana, buyurtmalar, tushum)
SELECT CURDATE(), COUNT(*), SUM(jami)
FROM buyurtmalar
WHERE DATE(yaratilgan) = CURDATE();
END //
DELIMITER ;
SHOW EVENTS;
DROP EVENT IF EXISTS loglarni_tozalash;
MySQL hodisalari qulay, lekin ko'p jamoalar operatsion tizim rejalashtiruvchisini
(cron, Windows Task Scheduler) afzal ko'radi:
- Kodni versiya nazoratida saqlash oson
- Jurnal va xatolarni kuzatish qulay
- Baza serveri yuklanmaydi
Hodisalar oddiy tozalash vazifalari uchun to'g'ri tanlov.
Bularni qachon ishlatish kerak? #
| Vosita | Ishlating | Ishlatmang |
|---|---|---|
| VIEW | Murakkab JOIN ni yashirish, xavfsizlik | Tezlashtirish uchun |
| Protsedura | Murakkab tranzaksiya, ommaviy amal | Oddiy CRUD |
| Funksiya | Takrorlanuvchi hisob | WHERE ichida |
| Trigger | Audit, qat'iy cheklov | Biznes mantiq |
| Hodisa | Tozalash, statistika | Murakkab vazifalar |
Bu eski bahs. Ikki yondashuv bor:
Bazada (protsedura, trigger):
- Ma'lumotga yaqin, tez
- Barcha ilovalar uchun bir xil qoidalar
- Lekin: versiya nazorati qiyin, test yozish qiyin, ko'chirish murakkab
Dastur kodida (PHP, Python):
- Git da saqlanadi, test yoziladi
- Nosozlikni tuzatish oson
- Bazani almashtirish oson
Zamonaviy amaliyot - mantiqni kodda saqlash, bazada esa faqat ma'lumot
butunligini himoya qiluvchi cheklovlar (FOREIGN KEY, CHECK, UNIQUE).
kutubxona bazasida:
kitob_royxatiVIEW yarating: kitob nomi, muallif ismi, janr, narx.- VIEW dan foydalanib janr bo'yicha statistikani chiqaring.
kitob_narxi_soliq(narx)funksiyasini yozing - QQS bilan narxni qaytarsin.janr_statistikasi(janr)protsedurasini yozing.ijaraga_berish(kitob_id, oquvchi_id)protsedurasini tranzaksiya bilan yozing - kitob mavjudligini tekshirsin vamavjudminiFALSEqilsin.narx_tarixijadvalini yarating va narx o'zgarishini yozadigan trigger qo'shing.BEFORE INSERTtrigger bilan kitob nomini avtomatikTRIMqiling.- Har kuni eski ijaralarni arxivlaydigan hodisa yarating.
Xulosa #
- VIEW - nomlangan so'rov; murakkablikni yashiradi, lekin tezlashtirmaydi.
- VIEW xavfsizlik uchun foydali - ustunlarni yashirish imkonini beradi.
- Protsedura murakkab amallarni bazada saqlaydi;
DELIMITERni unutmang. - Funksiya qiymat qaytaradi, lekin
WHEREda ishlatilsa indeksni buzadi. - Trigger avtomatik ishga tushadi - audit uchun yaxshi, biznes mantiq uchun yomon.
- Hodisalar rejalashtirilgan vazifalarni bajaradi.
- Zamonaviy amaliyot: mantiq kodda, cheklovlar bazada.
Keyingi bo'limda foydalanuvchilar va xavfsizlikni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.