Ma'lumot turlari — INTEGER, SERIAL, TEXT, BOOLEAN, TIMESTAMP, UUID, ARRAY, JSONB
Muammodan boshlaylik
Jadval yaratmoqchisiz. Foydalanuvchi uchun quyidagi ma'lumotlar kerak:
- id
- ism
- telefon raqami
- yosh
- balans (hisobdagi pul)
- faolmi yoki yo'qmi
- ro'yxatdan o'tgan vaqt
Har bir maydon uchun qaysi turni tanlash kerak? Noto'g'ri tanlasangiz:
- Telefon raqamini
INTEGERda saqlasangiz —+998901234567sig'maydi, boshidagi0yo'qoladi - Pulni
FLOATda saqlasangiz —100.10 + 200.20 = 300.3000000000003— yaxlitlash xatosi - Hamma narsani
TEXTqilsangiz —yoshga"yigirma besh"yoziladi, hisoblash bo'lmaydi
To'g'ri tur tanlash — database ning asosi.
Ma'lumot turi nima va nima uchun kerak?
Har bir ustun bitta turga ega. Bu tur:
- qanday ma'lumot saqlanishini belgilaydi
- noto'g'ri ma'lumot kiritilsa — database xato beradi
- diskda qancha joy egallashini aniqlaydi
- qanday hisob-kitob va qidiruv qilish mumkinligini ko'rsatadi
Hayotiy o'xshatma
Ofis jildlari. Har bir jild faqat ma'lum hujjat uchun: pasport jildi, shartnoma jildi, to'lov jildi. Pasport jildiga shartnoma solsangiz — tartib buziladi, kerak paytda topib bo'lmaydi. Ma'lumot turlari ham xuddi shunday — har bir ma'lumot o'z "jildida" saqlanadi.
Sonlar
INTEGER — butun son
Kundalik ishda eng ko'p ishlatiladigan son turi.
SMALLINT — -32,768 dan 32,767 gacha (2 bayt)
INTEGER — -2,147,483,648 dan 2,147,483,647 (4 bayt) ← eng ko'p ishlatiladigan
BIGINT — -9,223,372,036,854,775,808 dan … (8 bayt)
yosh INTEGER -- 0 dan 150 gacha yetarli
mahsulot_soni INTEGER -- oddiy miqdor
ko'rishlar BIGINT -- katta YouTube kanali: milliardan oshishi mumkin
Nima uchun BIGINT ni hamma joyda ishlatmaslik kerak? U INTEGER dan ikki barobar ko'p joy egallaydi. Millionlab qatorda bu sezilarli farq.
SERIAL — avtomatik o'sadigan son
id ustuni uchun. Har yangi qator qo'shilganda qiymat o'zi oshadi.
SERIAL — 1 dan 2,147,483,647 gacha (INTEGER asosida)
BIGSERIAL — 1 dan 9,223,372,036,854,775,807 gacha (BIGINT asosida)
CREATE TABLE foydalanuvchi (
id SERIAL PRIMARY KEY, -- ← 1, 2, 3, 4 ... o'zi ketadi
ism TEXT
);
INSERT INTO foydalanuvchi (ism) VALUES ('Ali'); -- id = 1 o'zi beriladi
INSERT INTO foydalanuvchi (ism) VALUES ('Vali'); -- id = 2
NUMERIC — aniq kasr son (pul uchun)
FLOAT va REAL — taxminiy qiymat saqlaydi, kichik xatolar bo'lishi mumkin. Pul uchun bu qabul qilinmas.
SELECT 0.1 + 0.2;
-- FLOAT: 0.30000000000000004 ← xato!
-- NUMERIC: 0.3 ← to'g'ri
NUMERIC(aniqlik, kasr) — jami raqam soni va kasr qismi:
narx NUMERIC(10, 2) -- 99999999.99 gacha, 2 ta kasr
foiz NUMERIC(5, 2) -- 999.99 gacha
balans NUMERIC(15, 2) -- pul uchun har doim NUMERIC
Matn
TEXT — cheksiz matn
Eng qulay matn turi. Uzunlik chegarasi yo'q.
ism TEXT
tavsif TEXT
xabar_matni TEXT
VARCHAR(n) — maksimal uzunlik bilan matn
telefon VARCHAR(20) -- +998901234567 — 13 belgi, 20 yetarli
kod VARCHAR(6) -- SMS kod: 123456
Nima uchun VARCHAR ni hamma joyga ishlatmaslik kerak? PostgreSQL da TEXT va VARCHAR bir xil tezlikda ishlaydi — VARCHAR ni faqat chegaralash mantiqan kerak bo'lganda ishlating, tezlik uchun emas.
CHAR(n) — qat'iy uzunlik
Har doim n belgidan iborat bo'ladi — qisqa bo'lsa bo'sh joy bilan to'ldiriladi.
davlat_kodi CHAR(2) -- "UZ", "US", "DE" — har doim 2 belgi
BOOLEAN — ha yoki yo'q
Faqat ikki qiymat: TRUE yoki FALSE.
faol BOOLEAN DEFAULT TRUE
email_tasdiqlangan BOOLEAN DEFAULT FALSE
SELECT * FROM foydalanuvchi WHERE faol = TRUE;
-- yoki qisqaroq:
SELECT * FROM foydalanuvchi WHERE faol;
Vaqt va sana
DATE — faqat sana
tug'ilgan_kun DATE -- 1995-03-15
TIME — faqat vaqt
ish_boshlanishi TIME -- 09:00:00
TIMESTAMP — sana va vaqt
yaratilgan_vaqt TIMESTAMP -- 2024-03-15 14:30:00
TIMESTAMPTZ — vaqt mintaqasi bilan
TIMESTAMP — "2024-03-15 14:30:00" — vaqt mintaqasini bilmaydi
TIMESTAMPTZ — "2024-03-15 14:30:00+05" — Toshkent vaqti, xalqaro loyihada to'g'ri
Nima uchun TIMESTAMPTZ ishlatish kerak? Foydalanuvchilar turli mamlakatda bo'lsa — Toshkentdagi "14:30" Moskvada "12:30", Londonda "09:30". TIMESTAMPTZ barchasini UTC da saqlaydi, kerak vaqtda har qanday mintaqaga o'giradi.
yaratilgan_vaqt TIMESTAMPTZ DEFAULT NOW() -- ← hozirgi vaqt avtomatik
yangilangan_vaqt TIMESTAMPTZ
┌─────────────┬────────────────────────────────────────────┐
│ Tur │ Ishlatish │
├─────────────┼────────────────────────────────────────────┤
│ DATE │ Tug'ilgan kun, bayram — vaqt kerak emas │
│ TIME │ Ish grafigi — sana kerak emas │
│ TIMESTAMP │ Faqat bitta mintaqali tizim │
│ TIMESTAMPTZ │ Xalqaro loyiha, turli vaqt mintaqalari │
└─────────────┴────────────────────────────────────────────┘
UUID — noyob identifikator
UUID — 128 bitli noyob qiymat. Ko'rinishi:
a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
SERIAL dan farqi nima?
SERIAL: 1, 2, 3, 4 ...
UUID: a0eebc99-..., f47ac10b-..., 6ba7b810-...
SERIAL — foydalanuvchi URL da ?id=5 ko'rsa, ?id=6 ni sinab ko'rishi mumkin. UUID bilan bu imkonsiz. Bundan tashqari bir nechta server parallel ishlasa SERIAL ning 1, 2, 3 qiymatlari to'qnashishi mumkin, UUID to'qnashmaydi.
CREATE TABLE foydalanuvchi (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY, -- ← o'zi generatsiya qiladi
ism TEXT
);
ARRAY — massiv
Bitta ustunda bir nechta qiymat saqlash:
CREATE TABLE mahsulot (
id SERIAL PRIMARY KEY,
nom TEXT,
rasmlar TEXT[], -- ← matn massivi
teglar TEXT[]
);
INSERT INTO mahsulot (nom, rasmlar, teglar)
VALUES (
'Noutbuk',
ARRAY['rasm1.jpg', 'rasm2.jpg', 'rasm3.jpg'],
ARRAY['elektronika', 'kompyuter']
);
Massivdan qidirish:
SELECT * FROM mahsulot
WHERE 'elektronika' = ANY(teglar); -- ← massiv ichida qidirish
Nima uchun ARRAY ehtiyotkorlik bilan ishlatiladi? Massiv ichidagi elementlarga JOIN qilib bo'lmaydi — ular alohida jadval emas. Ko'p-ko'p munosabat kerak bo'lsa — alohida jadval yaxshiroq.
JSONB — JSON ma'lumot
Tuzilmasi oldindan aniq bo'lmagan ma'lumotlar uchun. Har bir foydalanuvchining profil sozlamalari har xil bo'lishi mumkin:
CREATE TABLE foydalanuvchi (
id SERIAL PRIMARY KEY,
ism TEXT,
sozlamalar JSONB -- ← har kim uchun har xil bo'lishi mumkin
);
INSERT INTO foydalanuvchi (ism, sozlamalar) VALUES
('Ali', '{"til": "uz", "bildirishnoma": true}'),
('Vali', '{"til": "ru", "bildirishnoma": false, "mavzu": "qorong'"'"'i"}');
JSONB ichidan ma'lumot olish:
SELECT ism, sozlamalar->>'til' AS til
FROM foydalanuvchi;
-- ism │ til
-- ──────┼──────
-- Ali │ uz
-- Vali │ ru
JSON va JSONB farqi:
JSON — matnni xuddi shunday saqlaydi, o'qiyotganda tahlil qiladi
JSONB — ikkilik formatda saqlaydi, indekslanadi, qidiruv tez
Har doim JSONB ishlating — JSON ni faqat asl yozuvni aynan saqlash kerak bo'lsa ishlating.
Qaysi turni tanlash — umumiy qoida
┌─────────────────────────┬──────────────────────────────┐
│ Ma'lumot │ Tur │
├─────────────────────────┼──────────────────────────────┤
│ id (avtomatik) │ SERIAL yoki UUID │
│ Ism, email, matn │ TEXT │
│ Telefon, kod │ VARCHAR(n) │
│ Yosh, miqdor, soni │ INTEGER │
│ Katta son (views, like) │ BIGINT │
│ Pul, narx, foiz │ NUMERIC(10, 2) │
│ Ha/Yo'q │ BOOLEAN │
│ Sana │ DATE │
│ Vaqt muhim (log, audit) │ TIMESTAMPTZ │
│ Noyob ID (xavfsiz) │ UUID │
│ Rasmlar, teglar ro'yxat │ TEXT[] yoki alohida jadval │
│ O'zgaruvchan tuzilma │ JSONB │
└─────────────────────────┴──────────────────────────────┘
Tez-tez uchraydigan xatolar
Telefon raqamini INTEGER da saqlash
+998901234567 — 13 ta belgi, INTEGER sig'ishi qiyin. Boshidagi 0 yo'qoladi — 0901234567 o'rniga 901234567 saqlanadi. Telefon raqami — matn, hisob-kitob qilinmaydi:
-- ❌
telefon INTEGER
-- ✅
telefon VARCHAR(20)
Pulni FLOAT da saqlash
-- ❌
narx FLOAT -- 100.10 + 200.20 = 300.3000000000003
-- ✅
narx NUMERIC(10, 2) -- 100.10 + 200.20 = 300.30
Hamma joyda SERIAL, UUID kerak joyda SERIAL
Tashqi tizimlar bilan integratsiya, API, URL da id ko'rinadigan bo'lsa — UUID xavfsizroq. Faqat ichki jadvallar uchun SERIAL yetarli.
TIMESTAMP o'rniga TIMESTAMPTZ ishlatmaslik
Keyinchalik xalqaro foydalanuvchilar qo'shilsa — barcha vaqtlarni qayta hisoblash kerak bo'ladi. Boshidanoq TIMESTAMPTZ ishlating.
VARCHAR uzunligini kichik qo'yish
-- ❌ — email 255 belgigacha bo'lishi mumkin
email VARCHAR(50)
-- ✅
email TEXT -- yoki VARCHAR(255)
Xulosa
To'g'ri tur tanlash — ma'lumot sifati va tezligining asosi.
Asosiy qoidalar:
- Pul →
NUMERIC(10, 2), hech qachonFLOAT - Telefon →
VARCHAR(20), hech qachonINTEGER - Vaqt →
TIMESTAMPTZ, xalqaro loyihada majburiy - id →
SERIAL(oddiy) yokiUUID(xavfsiz, tashqi integratsiya) - O'zgaruvchan tuzilma →
JSONB, hech qachonJSON
Keyingi dars
5-dars: Schema — nima, yaratish, search_path, public schema