# SQL primary key va foreign key

> SQL'da primary key va foreign key nima? Har qatorni noyob qiladigan asosiy kalit va jadvallarni ishonchli bog'laydigan chet kalit tushunchalari misolda.

Manba: https://learncode.uz/sql/primary-foreign-key/
Sana: 2026-06-16

[JOIN](https://learncode.uz/sql/join) darsida jadvallar `id` va `mijoz_id` orqali bog'lanishini
ko'rgandik. Bu bog'lanish tasodifiy emas — uning ortida ikkita muhim
tushuncha turadi: **primary key** (asosiy kalit) va **foreign key** (chet
kalit). Ular ma'lumotning ishonchli va tartibli bo'lishini ta'minlaydi.

## Primary key — har qatorni noyob qiladi

**Primary key** — jadvaldagi har qatorni **noyob** ajratib turadigan ustun.
Namuna bazadagi har jadvalning `id` ustuni aynan shunday:

```sql
CREATE TABLE mijozlar (
  id     INTEGER PRIMARY KEY,
  ism    TEXT NOT NULL,
  shahar TEXT,
  yosh   INTEGER
);
```

O'zingiz ishga tushirib ko'ring — so'rovni tahrirlashingiz ham mumkin:

```sql
SELECT m.ism, p.nom
FROM buyurtmalar AS b
JOIN mijozlar    AS m ON b.mijoz_id    = m.id
JOIN mahsulotlar AS p ON b.mahsulot_id = p.id;
```

`id INTEGER PRIMARY KEY` ikki narsani kafolatlaydi:

- **Takrorlanmaydi** — ikki mijozda bir xil `id` bo'lolmaydi.
- **Bo'sh bo'lmaydi** — `id` hech qachon `NULL` bo'lmaydi.

Shu sababli `id = 4` deganda aniq bitta mijoz — Malika — tushuniladi. Agar
`id` takrorlanadigan bo'lsa, "4-mijoz" degani ma'nosini yo'qotardi.

> **Atama**
>
> **Kalit** (key) — qatorni aniqlash uchun ishlatiladigan ustun. **Primary
> key** har qatorni noyob belgilaydi. Odatda uni `id` deb nomlashadi va
> raqamli qilishadi, chunki raqamni solishtirish tez va ishonchli.

## Foreign key — jadvallarni bog'laydi

**Foreign key** — bir jadvaldagi ustun boshqa jadvalning primary key'iga
**ishora** qilsa, u chet kalit deyiladi. `buyurtmalar.mijoz_id` —
`mijozlar.id` ga foreign key:

```sql
CREATE TABLE buyurtmalar (
  id           INTEGER PRIMARY KEY,
  mijoz_id     INTEGER,
  mahsulot_id  INTEGER,
  soni         INTEGER NOT NULL,
  sana         TEXT,
  FOREIGN KEY (mijoz_id) REFERENCES mijozlar(id),
  FOREIGN KEY (mahsulot_id) REFERENCES mahsulotlar(id)
);
```

`FOREIGN KEY (mijoz_id) REFERENCES mijozlar(id)` bazaga aytadi: "`mijoz_id`
qiymati albatta `mijozlar` jadvalidagi mavjud `id` bo'lishi kerak".

## Foreign key nimadan himoya qiladi

Foreign key **butunlikni** saqlaydi. Uning yordamida baza ikki xatoga yo'l
qo'ymaydi:

- Mavjud bo'lmagan mijozga buyurtma qo'shib bo'lmaydi (masalan `mijoz_id = 99`,
  bunday mijoz yo'q).
- Buyurtmasi bor mijozni o'chirib bo'lmaydi — avval buyurtma hal qilinishi
  kerak. Aks holda "egasiz" buyurtmalar qolib ketardi.

<Callout type="warning" title="Boshlovchilar tez-tez yanglishadigan joy">
SQLite'da foreign key tekshiruvi standart holatda **o'chiq** turadi. Uni
yoqish uchun har sessiya boshida quyidagini bajaring:

```sql
PRAGMA foreign_keys = ON;
```

MySQL va PostgreSQL'da bu tekshiruv boshidan yoniq bo'ladi. Shuning uchun
SQLite'da sinayotganda buni unutmang.
</Callout>

<Callout type="example" title="O'zingizni sinab ko'ring">
Foreign key ishlayotganini tekshiring. `PRAGMA foreign_keys = ON;` dan keyin
mavjud bo'lmagan mijozga buyurtma qo'shib ko'ring:

```sql
INSERT INTO buyurtmalar (id, mijoz_id, mahsulot_id, soni)
VALUES (99, 50, 1, 1);
```

`mijoz_id = 50` li mijoz yo'q, shuning uchun baza bu buyurtmani **rad
etadi** — ma'lumot butunligi shunday himoyalanadi.
</Callout>

## Amaliy mashq

Kalitlarni tekshiring:

1. `buyurtmalar` dagi `mijoz_id` qaysi jadvalga ishora qilishini toping;
2. `JOIN` bilan uch jadvalni bog'lang;
3. mavjud bo'lmagan `mijoz_id` bilan buyurtma qo'shishga urining;
4. bir xil `id` bilan ikkita mijoz qo'shishga urining;
5. `PRAGMA foreign_keys = ON;` yozib, 3-qadamni takrorlang;
6. buyurtmasi bor mijozni (`id = 1`) o'chirishga urinib, natijani ko'ring.

4-qadamdagi xato PRIMARY KEY nima uchun kerakligini ko'rsatadi.

## Qisqacha xulosa

- **Primary key** — har qatorni noyob belgilaydigan ustun (odatda `id`);
  takrorlanmaydi va `NULL` bo'lmaydi.
- **Foreign key** — boshqa jadvalning primary key'iga ishora qiluvchi ustun.
- Foreign key **butunlikni** saqlaydi: mavjud bo'lmagan yozuvga ishora qilib
  yoki bog'liq yozuvni o'chirib bo'lmaydi.
- SQLite'da foreign key'ni `PRAGMA foreign_keys = ON;` bilan yoqing.
- Kalitlar `JOIN` uchun asos bo'ladi: jadvallar aynan shu ustunlar orqali
  bog'lanadi.

Keyingi darsda [`INDEX`](https://learncode.uz/sql/indeks) — jadval kattalashganda so'rovni qanday
tezlashtirishni ko'ramiz.
