VIEW — yaratish, yangilash, o'chirish, qachon kerak

~20 daq · MySQL · View, Stored Procedure, Trigger

Muammodan boshlaylik

Buyurtmaning to'liq ma'lumoti — 4 ta jadvaldan JOIN, summa hisobi, holat matni. Bu so'rov ilovada 6 joyda, hisobot skriptlarida 3 joyda, analitik uchun Excel ulanishida yana bir joyda yozilgan. Bir kuni "bekor qilingan buyurtmalar summaga kirmasin" degan qoida qo'shildi — 10 joyni topib o'zgartirish kerak.

Yana bir muammo: analitika jamoasiga mijozlar ro'yxatini berish kerak — lekin telefon va emailsiz (shaxsiy ma'lumot).

VIEW — saqlangan SELECT so'rovi, jadval kabi ishlatiladigan.


VIEW yaratish

CREATE VIEW buyurtmalar_toliq AS
SELECT
    b.id,
    b.yaratilgan,
    b.holat,
    m.id            AS mijoz_id,
    m.ism           AS mijoz,
    m.shahar,
    COUNT(q.id)              AS qatorlar,
    SUM(q.soni * q.narx)     AS summa
FROM buyurtmalar b
JOIN mijozlar m           ON m.id = b.mijoz_id
JOIN buyurtma_qatorlari q ON q.buyurtma_id = b.id
GROUP BY b.id, b.yaratilgan, b.holat, m.id, m.ism, m.shahar;

Endi oddiy jadval kabi:

SELECT * FROM buyurtmalar_toliq WHERE shahar = 'Toshkent';

SELECT mijoz, SUM(summa) AS jami
FROM buyurtmalar_toliq
WHERE holat <> 'bekor'
GROUP BY mijoz;
+-----------------+----------+
| mijoz           | jami     |
+-----------------+----------+
| Aziz Karimov    |  8140000 |
| Malika Rahimova | 21360000 |
+-----------------+----------+

Murakkab JOIN — bir joyda. Qoida o'zgarsa — faqat VIEW ni o'zgartirasiz.


VIEW ma'lumot saqlamaydi

VIEW — faqat so'rov matni. Har safar SELECT * FROM buyurtmalar_toliq chaqirilganda MySQL ichidagi so'rovni qaytadan bajaradi.

  • Ma'lumot doim yangi — jadvallar o'zgarsa, VIEW natijasi ham o'zgaradi
  • Diskda joy egallamaydi
  • Tezligi — ichidagi so'rov tezligi bilan bir xil. VIEW so'rovni tezlashtirmaydi

[!INFO] Boshqa bazalarda (PostgreSQL, Oracle) materialized view bor — natija haqiqatan saqlanadi va vaqti-vaqti bilan yangilanadi. MySQL da yo'q. O'xshash natija uchun — oddiy jadval + Event Scheduler bilan yangilash (34-dars, 44-dars).


Asosiy ishlatilishlar

1. Murakkab so'rovni soddalashtirish

Yuqoridagi misol. Hisobot yozuvchilar, analitiklar 4 ta JOIN ni bilishi shart emas.

2. Xavfsizlik — ustun va qatorlarni yashirish

CREATE VIEW mijozlar_analitika AS
SELECT id, shahar, yaratilgan, YEAR(yaratilgan) AS yil
FROM mijozlar;
-- ism, email, telefon — yo'q

CREATE USER 'analitik'@'%' IDENTIFIED BY '...';
GRANT SELECT ON dokon.mijozlar_analitika TO 'analitik'@'%';
-- mijozlar jadvaliga ruxsat YO'Q

Analitik faqat VIEW ni ko'radi — shaxsiy ma'lumotlarga yo'l yo'q (50-dars).

Qatorlarni ham cheklash mumkin:

CREATE VIEW toshkent_buyurtmalari AS
SELECT * FROM buyurtmalar_toliq WHERE shahar = 'Toshkent';
-- Toshkent filiali menejeri faqat o'z shahrini ko'radi

3. Barqaror interfeys

Ilova buyurtmalar_toliq dan o'qiydi. Ertaga siz mijozlar jadvalini ikkiga bo'lasiz (mijozlar + mijoz_manzillari). VIEW ni yangilaysiz — ilova o'zgarmaydi.

4. Soft delete filtri

CREATE VIEW faol_mijozlar AS
SELECT * FROM mijozlar WHERE ochirilgan IS NULL;

WHERE ochirilgan IS NULL ni unutish imkonsiz (12-dars).


O'zgartirish va o'chirish

CREATE OR REPLACE VIEW faol_mijozlar AS
SELECT id, ism, email, shahar FROM mijozlar WHERE ochirilgan IS NULL;

ALTER VIEW faol_mijozlar AS SELECT ...;

DROP VIEW IF EXISTS faol_mijozlar;

SHOW CREATE VIEW buyurtmalar_toliq\G
SHOW FULL TABLES WHERE Table_type = 'VIEW';

VIEW orqali yozish

Oddiy VIEW lar orqali INSERT, UPDATE, DELETE ham qilish mumkin — agar MySQL har bir VIEW qatorini asl jadvalning bitta qatoriga aniq moslashtira olsa:

UPDATE faol_mijozlar SET shahar = 'Buxoro' WHERE id = 4;   -- ✅ mijozlar jadvali o'zgaradi

Yangilanmaydigan VIEW lar — ichida bular bo'lsa:

  • GROUP BY, aggregate funksiyalar (SUM, COUNT)
  • DISTINCT, UNION
  • Ba'zi subquery lar
UPDATE buyurtmalar_toliq SET summa = 0 WHERE id = 1;
-- ERROR 1288: The target table buyurtmalar_toliq of the UPDATE is not updatable

summa — hisoblangan qiymat, uni "o'zgartirish" ma'nosiz.

WITH CHECK OPTION

CREATE VIEW toshkent_mijozlari AS
SELECT * FROM mijozlar WHERE shahar = 'Toshkent'
WITH CHECK OPTION;

UPDATE toshkent_mijozlari SET shahar = 'Samarqand' WHERE id = 1;
-- ERROR 1369: CHECK OPTION failed 'dokon.toshkent_mijozlari'

VIEW orqali yozilgan qator VIEW shartiga mos kelishi shart. Toshkent menejeri mijozni boshqa shaharga "chiqarib yubora" olmaydi.


Ehtiyot bo'ling

VIEW ustiga VIEW: v3 → v2 → v1 → jadvallar. Har biri "oddiy" ko'rinadi, lekin oxirida 12 ta JOIN va ikki marta guruhlash. EXPLAIN bilan tekshiring.

SELECT * VIEW ichida: VIEW yaratilganda * aniq ustunlar ro'yxatiga aylanadi. Keyin jadvalga ustun qo'shilsa — VIEW da ko'rinmaydi. VIEW ni qayta yaratish kerak.

Filtr VIEW ichiga kira olmasa: MySQL ko'pincha tashqi WHERE ni VIEW so'roviga qo'shib yuboradi (merge). Lekin GROUP BY, DISTINCT, LIMIT li VIEW larda — avval butun VIEW hisoblanadi (vaqtinchalik jadval), keyin filtrlanadi. Million qatorli guruhlash — faqat 1 ta mijoz uchun.


Nima uchun shunday?

Nima uchun VIEW natijani saqlamaydi — saqlasa tezroq bo'lmasmidi?

Saqlangan natija — eskiradi. Jadvalda har bir o'zgarish VIEW ni ham yangilashni talab qiladi, aks holda u yolg'on gapira boshlaydi. Oddiy VIEW bu muammoni umuman bilmaydi — u doim haqiqiy jadvallardan o'qiydi, shuning uchun doim to'g'ri. VIEW ning maqsadi — tezlik emas, abstraksiya: murakkablikni yashirish, huquqlarni cheklash, ilovani jadval tuzilmasidan ajratish.


Xulosa

Eslab qoling:

  • CREATE VIEW nom AS SELECT ... — saqlangan so'rov, jadval kabi ishlatiladi
  • Ma'lumot saqlamaydi; har safar qayta bajariladi; tezlashtirmaydi
  • Foydalari: murakkab JOIN ni yashirish, ustun/qatorlarni cheklash (xavfsizlik), barqaror interfeys
  • CREATE OR REPLACE VIEW — o'zgartirish
  • Oddiy VIEW lar orqali yozish mumkin; GROUP BY/aggregate li — yo'q
  • WITH CHECK OPTION — VIEW shartidan chiqib ketishni taqiqlash
  • VIEW ustiga VIEW va GROUP BY li VIEW — EXPLAIN bilan tekshiring

Keyingi dars

41-dars: Stored Procedure — IN, OUT, INOUT parametrlar