---
title: 'İç Birleştirme'
source: 'https://academia.sh/tr/kurslar/sql-temelleri/ic-birlestirme'
course: 'SQL Temelleri'
language: tr
updated: '2026-08-17T18:09:02+00:00'
license: 'CC BY-SA 4.0'
---

# İç Birleştirme

Normalleştirilmiş şemada dağılmış bilginin tek sonuçta toplanması, birleştirme koşulu, tablo takma adları, eşleşmeyen satırların düşmesi ve satır sayısının çoğalması.

Önceki konu tek tablodan okuyan sorguları kurdu: sütun seçimi, koşul, sıralama, boş değer
davranışı, işlevler. Bu araçlarla yanıtlanamayan bir soru kaldı. Ödünç tablosuna
bakıldığında hangi üyenin hangi kitabı aldığı görünmez.

Aşağıdaki blok şemayı ve örnek veriyi kurar; dersin bütün sorguları bu blokta oluşturulan
`kutuphane.db` dosyası üzerinde çalışır.

```sh
rm -f kutuphane.db
sqlite3 kutuphane.db <<'SQL'
CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL,
                    basim_yili INTEGER, sube_id INTEGER REFERENCES sube(sube_id));
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL,
                  eposta TEXT, kayit_tarihi TEXT NOT NULL);
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id),
                    uye_id INTEGER NOT NULL REFERENCES uye(uye_id), alis_tarihi TEXT NOT NULL,
                    iade_tarihi TEXT);
INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara'),
  (3,'Kadıköy','İstanbul'),(4,'Konak','İzmir');
INSERT INTO kitap VALUES (1,'Körlük','José Saramago',1995,1),(2,'Tutunamayanlar','Oğuz Atay',1972,1),
  (3,'Kum Kitabı','Jorge Luis Borges',1975,2),(4,'Yaban','Yakup Kadri',1932,2),
  (5,'Sessiz Ev','Orhan Pamuk',1983,3),(6,'Anayurt Oteli','Yusuf Atılgan',NULL,3),
  (7,'Tehlikeli Oyunlar','Oğuz Atay',1973,NULL);
INSERT INTO uye VALUES (1,'Ayşe','Demir','ayse@ornek.test','2023-02-14'),
  (2,'Mehmet','Kaya','mehmet@ornek.test','2023-05-30'),(3,'Zeynep','Arslan',NULL,'2024-01-09'),
  (4,'Emre','Yıldız','emre@ornek.test','2024-03-22'),(5,'Selin','Aydın',NULL,'2024-11-05'),
  (6,'Burak','Şahin','burak@ornek.test','2025-01-18');
INSERT INTO odunc VALUES (1,1,1,'2025-01-10','2025-01-24'),(2,2,1,'2025-02-02','2025-02-20'),
  (3,1,2,'2025-02-11',NULL),(4,3,3,'2025-03-01','2025-03-15'),(5,4,3,'2025-03-18','2025-04-02'),
  (6,1,4,'2025-04-05','2025-04-19'),(7,5,4,'2025-04-21',NULL),(8,2,5,'2025-05-02','2025-05-30'),
  (9,7,1,'2025-05-14','2025-05-28'),(10,3,5,'2025-06-03',NULL),(11,6,2,'2025-06-11','2025-06-25'),
  (12,4,4,'2025-06-20','2025-07-04');
SQL
```

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT odunc_id, kitap_id, uye_id, alis_tarihi FROM odunc WHERE odunc_id <= 4 ORDER BY odunc_id;
SQL
```

```
odunc_id  kitap_id  uye_id  alis_tarihi
--------  --------  ------  -----------
1         1         1       2025-01-10 
2         2         1       2025-02-02 
3         1         2       2025-02-11 
4         3         3       2025-03-01 
```

Görünen tek şey kimlikler. Bu bir eksiklik değil, normalleştirmenin doğrudan sonucudur:
üyenin adı üye tablosunda bir kez yazılır, ödünç kaydında yalnız ona başvuran yabancı
anahtar bulunur. Bilgi bilerek dağıtılmıştır; sorgunun işi onu geçici olarak toplamaktır.
Toplama işlemine **birleştirme** (join) denir.

## Birleştirme Koşulu

Birleştirme, iki tablonun satırlarını bir koşula göre eşleştirir. Yazımı `JOIN` ve `ON`
yan tümceleriyle kurulur.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT o.odunc_id, u.ad, u.soyad, o.alis_tarihi
FROM odunc AS o
JOIN uye AS u ON o.uye_id = u.uye_id
WHERE o.odunc_id <= 4
ORDER BY o.odunc_id;
SQL
```

```
odunc_id  ad      soyad   alis_tarihi
--------  ------  ------  -----------
1         Ayşe    Demir   2025-01-10 
2         Ayşe    Demir   2025-02-02 
3         Mehmet  Kaya    2025-02-11 
4         Zeynep  Arslan  2025-03-01 
```

Kimlikler adlara dönüştü. `ON` yan tümcesindeki koşul, ödünç kaydındaki yabancı anahtarı
üye tablosundaki birincil anahtarla eşliyor. Bu, birleştirmenin en yaygın biçimidir:
eşitlik koşuluyla yazılan ve **iç birleştirme** (inner join) adını taşıyan biçim. `JOIN`
sözcüğü tek başına yazıldığında iç birleştirme anlaşılır; `INNER JOIN` yazımı da aynı
şeydir.

`AS o` ve `AS u` yazımları tablolara **takma ad** verir. İki tabloda aynı adlı sütunlar
bulunduğunda — burada iki tabloda da `uye_id` var — hangi tablonun sütunundan söz edildiğini
takma ad belirler. Tek harflik takma adlar yaygındır ama tablo sayısı arttıkça
okunabilirliği düşürür; anlamlı kısaltmalar daha iyidir.

## Birden Çok Tablo

Birleştirme zincirlenebilir. Ödünç kaydı hem üyeye hem kitaba başvurduğu için, iki
birleştirme sorunun tamamını yanıtlar.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT o.odunc_id, u.ad || ' ' || u.soyad AS uye, k.baslik, o.alis_tarihi
FROM odunc AS o
JOIN uye AS u   ON o.uye_id = u.uye_id
JOIN kitap AS k ON o.kitap_id = k.kitap_id
ORDER BY o.odunc_id;
SQL
```

```
odunc_id  uye            baslik             alis_tarihi
--------  -------------  -----------------  -----------
1         Ayşe Demir     Körlük             2025-01-10 
2         Ayşe Demir     Tutunamayanlar     2025-02-02 
3         Mehmet Kaya    Körlük             2025-02-11 
4         Zeynep Arslan  Kum Kitabı         2025-03-01 
5         Zeynep Arslan  Yaban              2025-03-18 
6         Emre Yıldız    Körlük             2025-04-05 
7         Emre Yıldız    Sessiz Ev          2025-04-21 
8         Selin Aydın    Tutunamayanlar     2025-05-02 
9         Ayşe Demir     Tehlikeli Oyunlar  2025-05-14 
10        Selin Aydın    Kum Kitabı         2025-06-03 
11        Mehmet Kaya    Anayurt Oteli      2025-06-11 
12        Emre Yıldız    Yaban              2025-06-20 
```

Ödünç tablosundaki on iki kaydın hepsi döndü. Her birleştirme sonucu yeni bir bağıntıdır ve
bir sonraki birleştirmenin girdisi olur; sıra, yazıldığı sıradır ama motorun uyguladığı
sıra farklı olabilir — bildirimsel dilin kuralı burada da geçerlidir.

## Eşleşmeyen Satırlar Düşer

İç birleştirmenin tanımlayıcı özelliği, koşulu sağlamayan satırların sonuçta hiç
görünmemesidir. Kitapları şubeleriyle birleştiren sorgu bunu gösteriyor.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT k.baslik, s.ad AS sube
FROM kitap AS k
JOIN sube AS s ON k.sube_id = s.sube_id
ORDER BY k.kitap_id;
SQL
```

```
baslik          sube        
--------------  ------------
Körlük          Merkez      
Tutunamayanlar  Merkez      
Kum Kitabı      Bahçelievler
Yaban           Bahçelievler
Sessiz Ev       Kadıköy     
Anayurt Oteli   Kadıköy     
```

Altı satır döndü, oysa kitap tablosunda yedi kitap var. Eksik olan `Tehlikeli Oyunlar`:
şube kimliği boş olduğu için `k.sube_id = s.sube_id` koşulu hiçbir şube satırı için doğru
olmuyor. Beşinci dersteki kural burada da işliyor — boş değerle yapılan eşitlik ne doğru ne
yanlış üretir, ve birleştirme de yalnız doğruyu geçirir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT COUNT(*) AS kitap FROM kitap;
SELECT COUNT(*) AS birlestirme_sonucu FROM kitap AS k JOIN sube AS s ON k.sube_id = s.sube_id;
SQL
```

```
kitap
-----
7    
birlestirme_sonucu
------------------
6                 
```

Kaybın sessizliği önemlidir: sorgu hata vermez, bir eksik döndürür. Rapor sayıları
tutmadığında ilk bakılacak yerlerden biri, iç birleştirmenin elediği satırlardır.
Eşleşmeyen satırların da korunması gerekiyorsa dış birleştirme yazılır; sonraki dersin
konusu budur.

## Satır Sayısı Artabilir de

Birleştirme yalnız satır düşürmez, çoğaltabilir de. Bir tablodaki bir satır, diğer tabloda
birden çok satırla eşleşiyorsa sonuçta o kadar kez görünür.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT k.baslik, o.odunc_id, o.alis_tarihi
FROM kitap AS k
JOIN odunc AS o ON k.kitap_id = o.kitap_id
WHERE k.baslik = 'Körlük'
ORDER BY o.odunc_id;
SQL
```

```
baslik  odunc_id  alis_tarihi
------  --------  -----------
Körlük  1         2025-01-10 
Körlük  3         2025-02-11 
Körlük  6         2025-04-05 
```

Kitap tablosunda tek olan satır, ödünç kayıtlarıyla birleştiğinde üç kez göründü. Bu
doğrudur — üç ayrı ödünç işlemi var — ama sayım yapılırken tuzağa dönüşür: bu sonuç
üzerinden kitap sayılırsa `Körlük` üç kez sayılır. Toplama işlevleri konusunda bu ayrım
tekrar ele alınacak.

Genel kural: bire-çok bir ilişkide birleştirme, "bir" tarafındaki satırları "çok"
tarafındaki eşleşme sayısı kadar tekrarlar.

## Kısaltılmış Yazımlar

Birleştirmenin daha kısa iki yazımı vardır ve ikisi de dikkat ister.

Birincisi, birleştirme koşulunu iki tabloda aynı adı taşıyan sütuna dayandıran `USING`
yan tümcesidir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, ad AS sube FROM kitap JOIN sube USING (sube_id) ORDER BY kitap_id;
SQL
```

```
baslik          sube        
--------------  ------------
Körlük          Merkez      
Tutunamayanlar  Merkez      
Kum Kitabı      Bahçelievler
Yaban           Bahçelievler
Sessiz Ev       Kadıköy     
Anayurt Oteli   Kadıköy     
```

`USING (sube_id)` yazımı `ON k.sube_id = s.sube_id` ile aynı sonucu verir ve ortak sütunu
sonuçta bir kez gösterir. Adlandırma tutarlıysa yararlıdır; sütun adları farklıysa
kullanılamaz.

İkincisi, birleştirme koşulunu hiç yazmayan **doğal birleştirmedir** (natural join): iki
tabloda aynı adı taşıyan bütün sütunlar birleştirme koşulu sayılır. Kısalığı, sessiz
yanlışlık pahasına gelir.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT 'uye NATURAL JOIN sube satır sayısı: ' || COUNT(*) AS olcum FROM uye NATURAL JOIN sube;
SQL
```

```
olcum                                
-------------------------------------
uye NATURAL JOIN sube satır sayısı: 0
```

Üye ile şube tablosu arasında hiçbir anlamlı ilişki yok, ama ikisinde de `ad` adlı bir sütun
var. Doğal birleştirme bunu bir eşleştirme ölçütü sanıp üye adı ile şube adını karşılaştırdı
ve sıfır satır döndürdü. Hata iletisi yok; yalnız boş bir sonuç.

Asıl tehlike, şemaya sonradan eklenen bir sütunun adının bir başka tabloyla çakışmasıdır: o
gün doğru çalışan doğal birleştirme, ertesi gün sessizce başka bir şey hesaplamaya başlar.
Birleştirme koşulunu açıkça yazmak, bu sınıf hatayı tümüyle ortadan kaldırır.

Eski bir yazım daha vardır: tabloları virgülle ayırıp koşulu `WHERE` içine koymak.

```sh
sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT k.baslik, s.ad AS sube FROM kitap AS k, sube AS s
WHERE k.sube_id = s.sube_id ORDER BY k.kitap_id;
SQL
```

```
baslik          sube        
--------------  ------------
Körlük          Merkez      
Tutunamayanlar  Merkez      
Kum Kitabı      Bahçelievler
Yaban           Bahçelievler
Sessiz Ev       Kadıköy     
Anayurt Oteli   Kadıköy     
```

Sonuç aynı, ama iki kusuru var. Birleştirme koşulu ile süzme koşulu aynı yan tümcede
karışır; ve koşul unutulduğunda sorgu hata vermeden bütün eşleşme çiftlerini üretir. `ON`
yazımı koşulu birleştirmenin yanında tutarak her ikisini de önler.

## Özet

- Normalleştirilmiş şemada bilgi bilerek dağıtılır; birleştirme onu sorgu süresince
  geçici olarak toplar.
- İç birleştirme yalnız koşulu doğru olan satır çiftlerini döndürür; eşleşmeyen satır
  hata vermeden düşer.
- Boş değer taşıyan yabancı anahtar hiçbir satırla eşleşmez ve iç birleştirmede kaybolur.
- Bire-çok ilişkide birleştirme, "bir" tarafındaki satırı eşleşme sayısı kadar tekrarlar.
- Tablo takma adları aynı adlı sütunları ayırt eder ve çok tablolu sorguları okunabilir
  kılar.
- `USING` ortak adlı sütunda kısalık sağlar; doğal birleştirme koşulu ad benzerliğine
  bıraktığı için sessiz yanlışlığa açıktır.

## Sonraki Adım

İç birleştirmenin eşleşmeyen satırı düşürmesi, kimi sorularda tam olarak istenmeyen şeydir:
"hiç kitabı olmayan şube" ya da "hiç ödünç almamış üye" gibi sorular, tam da eşleşmesi
olmayan satırları arar. Sonraki ders bu satırları koruyan dış birleştirmeleri ele alır,
korunan satırların boş değerle nasıl dolduğunu gösterir ve sağ ile tam dış birleştirmenin
motor desteğine bağlı olduğunu ölçer.
