Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Butun sonlar
- 2.1 Uch o'lcham
- 2.2 Nega ID uchun bigint
- 3. Kasrli sonlar va pul
- 3.1 0.1 + 0.2 muammosi
- 3.2 numeric(p, s)
- 4. Matn
- 4.1 text, varchar(n), char(n)
- 4.2 varchar ga cast — jim kesish
- 4.3 Belgi va bayt
- 5. boolean
- 6. Vaqt turlari
- 6.1 To'rtta tur
- 6.2 timestamptz va timestamp farqi
- 6.3 date va interval
- 7. Maxsus turlar
- 7.1 uuid
- 7.2 jsonb va json
- 7.3 Massiv, bytea, inet
- 8. Qaysi tur qancha joy oladi
- 9. SQL qadami: vazifalar ustunlari turlari
- 10. Ko'p uchraydigan xatolar
- 10.1 Pul uchun float
- 10.2 Telefon — son emas
- 10.3 timestamp (zonasiz) bilan voqea vaqti
- 10.4 Sana — matn
- 10.5 varchar(n) ga cast bilan "tekshirish"
- 10.6 integer chegarasi
- 11. Mashqlar
- 1-mashq (oson): tur tanlang
- 2-mashq (o'rta): natijani oldindan ayting
- 3-mashq (qiyin): «Bahor» buyurtmalari jadvali
- 4-mashq: SQL qadami
- 12. Real ishda
- Xulosa
- Manbalar
PostgreSQL ma'lumot turlari: son, pul, matn, vaqt, UUID va JSON
Qisqacha: Har ustunning turi bor va u keyin o'zgartirish qiyin bo'lgan qaror. Asosiy qoidalar: identifikator —
bigint; pul —numeric(hech qachonreal/double precisionemas:0.1 + 0.2u yerda0.30000000000000004); matn —text(uzunlik chegarasi kerak bo'lsaCHECKbilan); vaqt nuqtasi —timestamptz(zonasiztimestampemas); faqat sana —date; davomiylik —interval; ha/yo'q —boolean. Telefon raqami va pochta indeksi — son emas,text.
Bu darsda
- Butun sonlar (
smallint,integer,bigint) chegaralarini va qachon qaysi birini olishni bilasiz. - Pul uchun nega
numerickerakligini0.1 + 0.2misolida isbotlaysiz. text,varchar(n)farqini vavarcharga cast qilishdagi jim kesish tuzog'ini tushuntirasiz.timestamptz,timestamp,datevaintervalni to'g'ri tanlaysiz.uuid,jsonb, massiv,byteavainetqayerda kerakligini va har tur qancha joy olishini aytasiz.
Oldin bilishingiz kerak: SQL tili va buyruq turlari, Number turi JS'da: EPSILON, MAX_SAFE_INTEGER, NaN va -0, Date va vaqt zonalari.
1. Nega bu kerak?
JavaScript'da son — number, matn — string, tamom. Bazada esa tanlov ko'p: son uchun beshta, matn uchun uchta, vaqt uchun to'rtta tur. Nega bunchalik?
Chunki noto'g'ri tur yillab yashaydigan xato beradi. Bir necha haqiqiy vaziyat:
- Narx
double precision(kasrli son) ustunida. Har kunlik hisobot bir necha tiyinga "adashadi" — buxgalter topolmaydi, chunki xato yaxlitlashda. - Telefon raqami son ustunida.
090…ning boshidagi nol yo'qoladi,+998ni esa umuman yozib bo'lmaydi. - Vaqt zonasiz saqlangan. Server Toshkentdan Frankfurtga ko'chirilgandan keyin hamma buyurtmalar 3–4 soat "siljiydi".
Bu xatolarni jadval to'lgandan keyin tuzatish og'ir: millionlab qatorni qayta yozish, ilovani to'xtatish kerak bo'lishi mumkin. Tur tanlash — uy qurishdan oldin poydevor tanlash kabi: keyin almashtirish deyarli imkonsiz.
Bu darsdagi SQL chiqishlari — kanon PostgreSQL 18.6 bazasida olingan. Ba'zi qo'shimcha misollarni o'z nusxamizda 17.6-bob ishga tushirdik — yonida aytilgan.
2. Butun sonlar
2.1 Uch o'lcham
| Tur | Bayt | Chegara (taxminan) | Qachon |
|---|---|---|---|
smallint |
2 | ±32 767 | kamdan-kam (yosh, reyting) |
integer (int) |
4 | ±2,1 milliard | soni, miqdori |
bigint |
8 | ±9,2 × 10¹⁸ | identifikatorlar, katta hisoblagichlar |
Chegaradan oshsa — Postgres jim "aylanib ketmaydi", xato beradi:
SELECT 2147483647::int + 1;ERROR: integer out of rangeTarjimasi: "butun son chegaradan tashqarida". ::int — tur o'zgartirish (cast): "bu qiymatni int deb hisobla". bigint da esa bemalol:
SELECT 2147483647::bigint + 1 AS bigint_yetadi; bigint_yetadi
---------------
2147483648
(1 row)2.2 Nega ID uchun bigint
2,1 milliard ko'p tuyuladi. Lekin ID'lar hech qachon qayta ishlatilmaydi: o'chirilgan qatorning raqami "kuyadi", bekor qilingan tranzaksiya ham raqam yeydi (Primary key tanlovi darsida ko'ramiz). Log, hodisa, xabar jadvallari yiliga yuz millionlab qator yig'adi. int ID tugab qolishi — real kompaniyalarda bo'lgan avariya: yangi qator yozib bo'lmay qoladi.
bigint atigi 4 bayt ko'proq oladi. Kanon qarori: hamma ID — bigint.
Maslahat: JavaScript'ning
numberturi butun sonni faqat 2⁵³ gacha aniq saqlaydi,bigintesa 2⁶³ gacha boradi. Shuning uchun Node.js'dagipgkutubxonasibigintni satr qilib qaytaradi. Buni node-postgres (pg) asoslari darsida hal qilamiz.
3. Kasrli sonlar va pul
3.1 0.1 + 0.2 muammosi
Number turi JS'da: EPSILON, MAX_SAFE_INTEGER, NaN va -0 darsida JS'da 0.1 + 0.2 === 0.3 → false ekanini ko'rgansiz. Postgres'ning real (4 bayt) va double precision (float8, 8 bayt) turlari JS'dagi number bilan bir xil standartda (IEEE 754) — xato ham bir xil. numeric esa sonni o'nlik raqamlar sifatida aniq saqlaydi:
SELECT 0.1::float8 + 0.2::float8 = 0.3::float8 AS float_teng,
0.1::numeric + 0.2::numeric = 0.3 AS numeric_teng,
(0.1::float8 + 0.2::float8)::text AS float_aslida; float_teng | numeric_teng | float_aslida
------------+--------------+---------------------
f | t | 0.30000000000000004
(1 row)float8 da 0.1 + 0.2 0.3 ga teng emas. Bu bitta qo'shishda. Ko'p qo'shishda xato to'planadi — o'nta 0.1 ni qo'shamiz. generate_series(1, 10) — 1 dan 10 gacha 10 ta qator yasaydigan funksiya, sum — ularni qo'shadi. Bu so'rovni biz ishga tushirdik (PG 17.6; kanon 18.6 da ham aynan shu raqamlar):
SELECT sum(0.1::float8) AS float_yigindi,
sum(0.1::numeric) AS numeric_yigindi
FROM generate_series(1, 10); float_yigindi | numeric_yigindi
--------------------+-----------------
0.9999999999999999 | 1.0
(1 row)Do'konning kunlik hisobotida minglab qator qo'shiladi. Kanon Pul, miqdor va enum'larni modellash darsi uchun 1 mln marta 0.1 ni qo'shdi: float8 — 100000.00000133288, numeric — aniq 100000.0000.
3.2 numeric(p, s)
numeric(10,2) — jami 10 ta raqam, shundan 2 tasi verguldan keyin. Ortiqcha kasr yaxlitlanadi:
SELECT 12345.678::numeric(10,2) AS yaxlitlandi; yaxlitlandi
-------------
12345.68
(1 row)Butun qism sig'masa — xato:
SELECT 123456789.12::numeric(10,2) AS sigmaydi;ERROR: numeric field overflow
DETAIL: A field with precision 10, scale 2 must round to an absolute value less than 10^8.Tarjimasi: "numeric maydoni to'lib ketdi. Aniqligi 10, kasr qismi 2 bo'lgan maydon 10⁸ dan kichik bo'lishi kerak". 10 raqamdan 2 tasi kasrga ketgan, butun qismga 8 ta qoladi.
Pul uchun ikki to'g'ri yo'l bor: numeric(12,2) (so'm va tiyin) yoki bigint da eng kichik birlikda (tiyinlarda) saqlash. Ikkalasini Pul, miqdor va enum'larni modellash darsida solishtiramiz. Noto'g'ri yo'l bitta — real/double precision.
float qachon to'g'ri? Taxminiy o'lchovlar: harorat, koordinata, ilmiy hisob. U yerda oxirgi raqamdagi farq ahamiyatsiz, tezlik esa muhim.
Tekshirib ko'ring: Mahsulot og'irligi (kg, 3 xonali aniqlik), valyuta kursi (11 903.15) va GPS koordinata — har biriga qaysi tur?
Javob
Og'irlik — numeric(10,3): aniq qiymat, hisob-kitobga kiradi (narx × og'irlik). Valyuta kursi — numeric (masalan numeric(12,4)): pul hisobida qatnashadi. GPS koordinata — double precision yoki maxsus geo tur (PostGIS): taxminiy o'lchov, millimetrlik farq muhim emas.
4. Matn
4.1 text, varchar(n), char(n)
| Tur | Ma'nosi | Tavsiya |
|---|---|---|
text |
istalgan uzunlik | asosiy tanlov |
varchar(n) |
ko'pi bilan n belgi | chegarani CHECK bilan qilish afzal |
char(n) |
aynan n belgi, bo'sh joy bilan to'ldiriladi | ishlatmang |
Postgres'da text va varchar(n) bir xil saqlanadi, tezligi ham bir xil. varchar(255) — boshqa bazalardan qolgan odat; Postgres'da 255 ning maxsus ma'nosi yo'q. Uzunlikni cheklash kerak bo'lsa, ikkala usul ishlaydi:
CREATE TEMP TABLE t11 (
v varchar(5),
t text CHECK (char_length(t) <= 5)
);
INSERT INTO t11 VALUES ('Assalomu', 'ok');
INSERT INTO t11 VALUES ('ok', 'Assalomu');CREATE TABLE
ERROR: value too long for type character varying(5)
ERROR: new row for relation "t11" violates check constraint "t11_t_check"
DETAIL: Failing row contains (ok, Assalomu).Ikkalasi ham uzun matnni rad etdi. CHECK ning afzalligi: chegarani keyin o'zgartirish faqat cheklovni almashtirish, ustun turiga tegilmaydi. Cheklovlarni CREATE TABLE va cheklovlar darsida batafsil ko'ramiz.
4.2 varchar ga cast — jim kesish
Mana kutilmagan tuzoq. INSERT xato berdi, lekin cast boshqacha ishlaydi:
SELECT 'Assalomu alaykum'::varchar(5); varchar
---------
Assal
(1 row)Xato yo'q — matn jimgina 5 belgiga kesildi. Bu SQL standartida yozilgan qoida: ochiq cast (::varchar(5)) ortiqchani kesadi, ustunga yozish esa xato beradi. Kodda "tekshirish" uchun cast ishlatsangiz, ma'lumot ogohlantirishsiz yo'qoladi.
4.3 Belgi va bayt
Matn diskda UTF-8 kodlashda saqlanadi. Lotin harfi — 1 bayt, lekin ba'zi belgilar ko'proq oladi. O'zbekcha ʻ (to'g'ri o'zbek apostrofi, U+02BB) — 2 bayt:
SELECT length('Oʻzbekiston') AS belgi,
octet_length('Oʻzbekiston') AS bayt,
length('O''zbekiston') AS apostrof_bilan; belgi | bayt | apostrof_bilan
-------+------+----------------
11 | 12 | 11
(1 row)length (yoki char_length) belgilarni sanaydi — 11. octet_length baytlarni — 12. "Ko'pi bilan 100 belgi" qoidasi doim char_length bilan yoziladi. JS'dagi .length boshqacha sanaydi (UTF-16 birliklari): emoji JS'da 2, Postgres'da 1 belgi. Kanon bu farqni vazifalar sxemasida qayd etgan.
5. boolean
boolean — true, false yoki NULL. Postgres kiritishda bir nechta yozuvni tushunadi:
SELECT 'yes'::boolean, 'f'::boolean, 1::boolean; bool | bool | bool
------+------+------
t | f | t
(1 row)psql uni t/f deb ko'rsatadi. Holatni "ha"/"yo'q" matni yoki 0/1 son bilan saqlamang — boolean 1 bayt va ma'nosi aniq.
6. Vaqt turlari
6.1 To'rtta tur
| Tur | Nima saqlaydi | Misol |
|---|---|---|
timestamptz |
vaqt nuqtasi (zona bilan) | buyurtma yaratilgan payt |
timestamp |
"devordagi soat", zonasiz | kamdan-kam kerak |
date |
faqat sana | tug'ilgan kun, yetkazish kuni |
interval |
davomiylik | "30 daqiqa", "1 oy" |
6.2 timestamptz va timestamp farqi
Nomi chalg'itadi: timestamptz (timestamp with time zone) zonani saqlamaydi. U kiritilgan vaqtni UTC'ga aylantirib saqlaydi va chiqarishda sessiya zonasiga o'giradi. timestamp (without time zone) esa yozilgan raqamlarni hech qanday zonasiz, shundayligicha saqlaydi.
Kanon ikkalasini Toshkent va UTC zonalarida solishtirdi. Toshkent zonasida:
SET TIME ZONE 'Asia/Tashkent';
SELECT '2026-10-24 09:00'::timestamptz AS tz,
'2026-10-24 09:00'::timestamp AS zonasiz;SET
tz | zonasiz
------------------------+---------------------
2026-10-24 09:00:00+05 | 2026-10-24 09:00:00
(1 row)UTC zonasida, Toshkentdagi soat 9 ni berib:
SET TIME ZONE 'UTC';
SELECT '2026-10-24 09:00+05'::timestamptz AS tz_utc_da,
'2026-10-24 09:00'::timestamp AS zonasiz_ozgarmadi;SET
tz_utc_da | zonasiz_ozgarmadi
------------------------+---------------------
2026-10-24 04:00:00+00 | 2026-10-24 09:00:00
(1 row)timestamptz bir xil lahzani ko'rsatdi: Toshkentda 09:00 = UTC'da 04:00. timestamp esa shunchaki "09:00" — qaysi shahar soatiga tegishli ekanini bilmaydi. Ilova, server va foydalanuvchi turli zonalarda bo'lishi mumkin — shuning uchun voqea vaqti doim timestamptz. Zonalarni chuqur SQL'da sana va vaqt zonalari darsida o'rganamiz.
6.3 date va interval
SELECT '2026-10-24'::date + 7 AS bir_haftadan_keyin,
'2026-11-01'::date - '2026-10-24'::date AS kun_farqi,
interval '1 day 2 hours' * 3 AS uch_marta,
'2026-01-31'::date + interval '1 month' AS oy_qoshish; bir_haftadan_keyin | kun_farqi | uch_marta | oy_qoshish
--------------------+-----------+-----------------+---------------------
2026-10-31 | 8 | 3 days 06:00:00 | 2026-02-28 00:00:00
(1 row)To'rt narsaga qarang:
date + 7— 7 kun qo'shildi.- Ikki sana ayirmasi — kunlar soni (butun son).
intervalni songa ko'paytirish mumkin.- 31-yanvarga 1 oy qo'shsak — 28-fevral. 31-fevral yo'q, Postgres oyning oxirgi kunini oldi. Obuna va to'lov muddatlarida bu muhim tafsilot.
Noto'g'ri sanani Postgres qabul qilmaydi (biz o'z nusxamizda sinadik, PostgreSQL 17.6):
SELECT '2026-02-30'::date;ERROR: date/time field value out of range: "2026-02-30"
LINE 1: SELECT '2026-02-30'::date;
^Sanani matn qilib saqlasangiz, bunday himoya yo'q. Ustiga, matnlar harf bo'yicha solishtiriladi:
SELECT '24.10.2026' < '3.01.2026' AS matn_solishtirish; matn_solishtirish
-------------------
t
(1 row)Nima bo'ldi? Natija — rost (t): birinchi belgilar solishtirildi, '2' belgisi '3' dan kichik. Garchi oktabr yanvardan keyin bo'lsa ham.
Tekshirib ko'ring: Foydalanuvchining tug'ilgan kuni, xabar yuborilgan payt va obuna davomiyligi — qaysi turlar?
Javob
Tug'ilgan kun — date: soat ham, zona ham kerak emas (Toshkentda ham, Nyu-Yorkda ham 15-mart). Xabar yuborilgan payt — timestamptz: aniq lahza, turli zonadagi odamlar o'z vaqtida ko'rishi kerak. Obuna davomiyligi — interval ('1 month', '1 year').
7. Maxsus turlar
7.1 uuid
UUID — 128 bitli noyob identifikator, xxxxxxxx-xxxx-… ko'rinishida. gen_random_uuid() tasodifiy (v4) UUID beradi. PostgreSQL 18 da yangi uuidv7() funksiyasi qo'shildi — uning boshida vaqt bor, shuning uchun ketma-ket yaratilganlari tartib bilan o'sadi:
Natija har safar boshqa qiymat bo'ladi, shuning uchun bu yerda kanon chiqishini ko'rsatamiz:
SELECT gen_random_uuid() AS v4, uuidv7() AS v7;Kanon chiqishi:
v4 | v7
--------------------------------------+--------------------------------------
01180400-e9ec-4e53-8946-06a93bd541b9 | 01a16c44-c2e7-7239-baa3-0de75f6c44de
(1 row)v7 dagi uchinchi guruh 7 bilan boshlanadi — versiya raqami. uuidv7() PostgreSQL 17 da yo'q: biz o'z nusxamizda sinaganda function uuidv7() does not exist xatosini oldik. UUID qachon ID bo'lishi kerakligini va v4/v7 tezlik farqini Primary key tanlovi darsida o'lchaymiz.
7.2 jsonb va json
Ikkala tur JSON saqlaydi, lekin farqi bor:
SELECT '{"b": 1, "a": [1, 2]}'::jsonb AS jsonb_tartib,
'{"b": 1, "a": [1, 2]}'::json AS json_matn; jsonb_tartib | json_matn
-----------------------+-----------------------
{"a": [1, 2], "b": 1} | {"b": 1, "a": [1, 2]}
(1 row)json matnni aynan saqlaydi (bo'shliqlar, kalitlar tartibi bilan). jsonb uni ikkilik ko'rinishga o'giradi: kalitlar tartiblanadi, takror kalit olib tashlanadi, lekin ichidan qidirish va indeks qurish mumkin. Deyarli har doim — jsonb. Uni JSONB darsida chuqur o'rganamiz. Diqqat: JSON ustuni — relatsion jadvallar o'rnini bosuvchi emas (DB turlari xaritasi va SQL vs NoSQL darsidagi hujjat modeli kamchiliklari shu yerda ham bor).
7.3 Massiv, bytea, inet
SELECT ARRAY['#uy', '#bozor'] AS teglar,
(ARRAY['#uy', '#bozor'])[1] AS birinchi,
'#uy' = ANY(ARRAY['#uy', '#bozor']) AS bormi; teglar | birinchi | bormi
--------------+----------+-------
{#uy,#bozor} | #uy | t
(1 row)- Massiv — har tur uchun (
text[],int[]). Diqqat: Postgres massivlari 1 dan boshlanadi, JS'dagidek 0 dan emas. Massiv ichida bog'lanish (teglar → boshqa jadval) qo'yib bo'lmaydi — shuning uchun kanon teglarni alohida jadvalda saqlaydi. bytea— ikkilik ma'lumot ('salom'::bytea→\x73616c6f6d). Kichik fayl yoki hash uchun. Katta fayllar (rasm, video) bazada emas, fayl omborida saqlanadi.inet/cidr— IP manzil va tarmoq. Kanon misolida'192.168.1.15'::inet << '192.168.1.0/24'::cidr→t("bu IP shu tarmoq ichida"). IP'larni matn emas,inetda saqlash tekshiruv va tarmoq amallarini beradi.
8. Qaysi tur qancha joy oladi
Kanon pg_column_size funksiyasi bilan har turdagi bitta qiymat o'lchamini o'lchadi:
- boolean1 bayt
- smallint2 bayt
- integer4 bayt
- bigint8 bayt
- timestamptz8 bayt
- text 'salom'5 bayt + 4 bayt sarlavha9 bayt
- uuid16 bayt
Manba: IlmHamroh kanon o'lchovi, 2026-10-24: PostgreSQL 18.6, pg_column_size; numeric 1.5 — 10 bayt
Nimaga qarang: bigint va timestamptz — 8 bayt, uuid — 16 bayt, ya'ni bigint dan ikki baravar. Bitta qatorda farq kichik. 2 mln qatorli jadvalda va uning indekslarida esa megabaytlarga aylanadi. Matn qisqa bo'lsa ham kichik "sarlavha" qo'shiladi ('salom' — 5 harf, 9 bayt). Telefon raqami '+998 90 000 00 00' matn sifatida — 21 bayt, son sifatida esa 8 bayt bo'lardi (biz o'z nusxamizda o'lchadik). Lekin pastdagi «Telefon — son emas» xatosiga qarang: to'g'rilik joydan muhimroq.
flowchart TD
Q{Ustunda nima?} --> N[Butun son] --> NB[ID: bigint<br/>soni: integer]
Q --> P[Pul] --> PN[numeric yoki<br/>bigint tiyinda]
Q --> T[Matn] --> TT[text + CHECK]
Q --> V[Vaqt] --> VT[lahza: timestamptz<br/>kun: date]
Q --> B[Ha/yo'q] --> BB[boolean]Nimaga qarang: har savolga bitta asosiy javob. Istisnolar bor, lekin ular sababli bo'lishi kerak.
9. SQL qadami: vazifalar ustunlari turlari
CREATE TABLE va cheklovlar darsida yaratiladigan ikki jadval uchun kanon turlarni shunday tanlagan:
| Ustun | Tur | Nega |
|---|---|---|
id |
bigint |
ID tugab qolmasin |
email, ism |
text |
uzunlik CHECK bilan |
matn |
text |
CHECK — 1–100 belgi (frontend qoidasi) |
bajarildi |
boolean |
ha/yo'q |
yaratilgan_vaqt |
timestamptz |
aniq lahza, zona bilan |
matn uchun varchar(100) emas, text + CHECK (char_length(matn) BETWEEN 1 AND 100): chegara 22-qismdagi frontend'ning Vazifa.MAKS_UZUNLIK = 100 qoidasi bilan bir xil va keyin o'zgarsa, faqat cheklov almashtiriladi. Bu darsda fayl yozilmaydi va commit yo'q.
10. Ko'p uchraydigan xatolar
10.1 Pul uchun float
real/double precision da pul — yaxlitlash xatolari to'planadi (0.9999999999999999). Pul — numeric yoki bigint (tiyinda).
10.2 Telefon — son emas
Biz telefon raqamini songa aylantirib ko'rdik (PostgreSQL 17.6):
SELECT '0900000000'::bigint AS telefon; telefon
-----------
900000000
(1 row)Boshidagi nol yo'qoldi. +998 va bo'shliqlarni esa son umuman saqlamaydi. Qoida: arifmetika qilinmaydigan "raqam" — telefon, pochta indeksi, pasport seriyasi, karta raqami — text.
10.3 timestamp (zonasiz) bilan voqea vaqti
Server zonasi o'zgarsa yoki foydalanuvchilar turli zonada bo'lsa, zonasiz vaqt noto'g'ri talqin qilinadi. Voqea vaqti — timestamptz.
10.4 Sana — matn
'24.10.2026' matni noto'g'ri tartiblanadi (yuqorida t), '30.02.2026' ni ham qabul qiladi. Sana — date.
10.5 varchar(n) ga cast bilan "tekshirish"
::varchar(5) xato bermaydi, jimgina kesadi. Chegara — CHECK yoki ustun turida, cast'da emas.
10.6 integer chegarasi
integer out of range — ko'pincha ID yoki hisoblagichda. bigint dan boshlang; keyin int → bigint o'zgartirish katta jadvalda uni qayta yozadi (kanon 1 mln qatorda 512 ms o'lchagan — ALTER TABLE va sxemani o'zgartirish darsida).
11. Mashqlar
Mashqlar kurs/mashqlar/26/11-turlar/ da.
1-mashq (oson): tur tanlang
- Mahsulot narxi so'mda tiyini bilan — .
- Buyurtma yaratilgan aniq lahza — .
- Foydalanuvchi ID'si — .
- "Yetkazildimi?" — .
- Tug'ilgan kun — .
- Telefon raqami — .
Yechim
numeric (yoki numeric(12,2); muqobil — bigint tiyinda), timestamptz, bigint, boolean, date, text. Telefon — text, chunki u bilan arifmetika qilinmaydi va boshidagi +, 0 saqlanishi kerak.
2-mashq (o'rta): natijani oldindan ayting
Har so'rov nima qaytaradi yoki qanday xato beradi?
SELECT 0.1::numeric + 0.2::numeric;SELECT 'Toshkent'::varchar(4);SELECT '2026-03-31'::date + interval '1 month';SELECT 40000::smallint;SELECT (ARRAY[10, 20, 30])[0];
Yechim
0.3—numericaniq.Tosh— cast jim kesadi.2026-04-30 00:00:00— 31-aprel yo'q, oyning oxirgi kuni olinadi.ERROR: smallint out of range—smallintning chegarasi 32 767.NULL(psql'da bo'sh) — massivlar 1 dan boshlanadi, 0-element yo'q. Xato emas,NULL— bu ham tuzoq.
Biz 1–5 ni o'z nusxamizda ham tekshirdik (PostgreSQL 17.6): natijalar shunday.
3-mashq (qiyin): «Bahor» buyurtmalari jadvali
«Bahor» oshxonasi yetkazib berish buyurtmalari uchun jadval yarating: id, telefon, summa (so'm, tiyin bilan), tolandi (sukut false), yaratilgan (aniq lahza), yetkazish (faqat kun). Ikkita qator qo'shing (Toshkent vaqti bilan 2026-10-24 21:30 va 23:50, yetkazish 25- va 31-oktabr). So'rovlar:
- Hamma summalar yig'indisi.
- Har buyurtma uchun yetkazishgacha necha kun qoldi (yaratilgan kunidan) va yaratilgan vaqt UTC'da.
telefonvasummaqiymatlarining bayt o'lchami (pg_column_size).
CREATE TABLE sintaksisini CREATE TABLE va cheklovlar darsida to'liq o'rganamiz — hozir yechimdagi namunaga qarab yozing. AT TIME ZONE 'UTC' — lahzani UTC soatida ko'rsatadi, ::date — sessiya zonasidagi kun.
Yechim
SET TIME ZONE 'Asia/Tashkent';
CREATE TABLE buyurtmalar (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
telefon text NOT NULL,
summa numeric(12,2) NOT NULL,
tolandi boolean NOT NULL DEFAULT false,
yaratilgan timestamptz NOT NULL,
yetkazish date
);
INSERT INTO buyurtmalar (telefon, summa, yaratilgan, yetkazish) VALUES
('+998 90 000 00 01', 105000, '2026-10-24 21:30+05', '2026-10-25'),
('+998 90 000 00 02', 0.1, '2026-10-24 23:50+05', '2026-10-31');
SELECT sum(summa) AS jami FROM buyurtmalar;
SELECT id, yetkazish - yaratilgan::date AS kun_qoldi,
yaratilgan AT TIME ZONE 'UTC' AS utc_vaqt
FROM buyurtmalar ORDER BY id;
SELECT pg_column_size(telefon) AS telefon_bayt,
pg_column_size(summa) AS summa_bayt
FROM buyurtmalar WHERE id = 1;Natija (PostgreSQL 17.6):
SET
CREATE TABLE
INSERT 0 2
jami
-----------
105000.10
(1 row)
id | kun_qoldi | utc_vaqt
----+-----------+---------------------
1 | 1 | 2026-10-24 16:30:00
2 | 7 | 2026-10-24 18:50:00
(2 rows)
telefon_bayt | summa_bayt
--------------+------------
18 | 7
(1 row)numeric tiyinni aniq qo'shdi (105000.10). 23:50 dagi buyurtma Toshkentda 24-oktabrda yaratilgan, UTC'da ham hali 24-chi (18:50). Agar u 2026-10-25 01:00 da (Toshkent) yaratilganida — Toshkent kuni 25, UTC kuni esa 24 bo'lardi: ::date qaysi zonada hisoblanishi muhim. numeric qiymati hajmi raqamlar soniga bog'liq (bu yerda 7 bayt).
Telefon nega 18 bayt, «Qaysi tur qancha joy oladi» bo'limida esa 21 edi? U yerda biz alohida qiymatni o'lchadik — unga 4 baytlik sarlavha qo'shiladi (17 belgi + 4). Jadvalga yozilgan qisqa matn esa ixcham saqlanadi: sarlavha 1 bayt (17 + 1 = 18). Ikkala raqam ham haqiqiy — nimani o'lchayotganingizga qarang.
4-mashq: SQL qadami
«SQL qadami» jadvaliga foydalanuvchilar uchun yana ikkita ustun taklif qiling: oxirgi kirgan vaqti va tug'ilgan sanasi (ixtiyoriy). Turlarini va nega aynan shunday ekanini yozing.
Yechim
oxirgi_kirish timestamptz — aniq lahza, foydalanuvchi qaysi zonada bo'lishidan qat'i nazar to'g'ri. tugilgan_sana date — faqat kun, soat va zona ma'nosiz. Ikkalasi ham NULL bo'lishi mumkin (hali kirmagan yoki sanani bermagan). Kanon sxemasida bu ustunlar yo'q — bu mashq faqat tur tanlash uchun.
12. Real ishda
- Kod review:
floatustunidagi narx,varchar(255)hamma joyda,timestamp(zonasiz) — review'da birinchi so'raladigan savollar. - Migratsiya narxi:
int→bigintyokitimestamp→timestamptzkatta jadvalda uzoq qulf va to'xtash talab qiladi. Tur bir martada to'g'ri tanlanadi. - API bilan chegara: JSON'da
bigintvanumericko'pincha satr bo'lib boradi (JSnumberaniqligi yetmaydi),timestamptz— ISO 8601 satri (2026-10-24T04:00:00Z). - Intervyu savollari: "Pulni qaysi turda saqlaysiz va nega?", "
timestampvatimestamptzfarqi?", "textvavarcharfarqi Postgres'da?".
Xulosa
- Butun son:
integer(4 bayt),bigint(8 bayt) — ID uchunbigint; chegaradan oshish — xato (integer out of range). - Pul —
numeric(yoki tiyindabigint);float8da0.1 + 0.2 = 0.30000000000000004, o'nta 0.1 —0.9999999999999999. - Matn —
text+CHECK;::varchar(n)cast jim kesadi;char_length— belgi,octet_length— bayt (ʻ— 2 bayt). - Vaqt nuqtasi —
timestamptz(ichida UTC), kun —date, davomiylik —interval; 31-yanvar + 1 oy = 28-fevral. uuid(uuidv7()— PG 18),jsonb(kalitlar tartiblanadi), massiv (1 dan boshlanadi),bytea,inet; telefon va indeks —text.
Keyingi dars: CREATE TABLE va cheklovlar — vazifalar bazasining birinchi ikki jadvalini cheklovlar bilan yaratamiz.
Manbalar
- PostgreSQL 18 hujjati — Data Types: https://www.postgresql.org/docs/18/datatype.html
- PostgreSQL 18 hujjati — Numeric Types: https://www.postgresql.org/docs/18/datatype-numeric.html
- PostgreSQL 18 hujjati — Character Types: https://www.postgresql.org/docs/18/datatype-character.html
- PostgreSQL 18 hujjati — Date/Time Types: https://www.postgresql.org/docs/18/datatype-datetime.html
- PostgreSQL 18 hujjati — UUID Functions (
uuidv7): https://www.postgresql.org/docs/18/functions-uuid.html - PostgreSQL Wiki — Don't Do This: https://wiki.postgresql.org/wiki/Don%27t_Do_This
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!