---
title: "Mikro ERP Tablo İlişkileri ve JOIN Rehberi: Hangi Tablo Hangisiyle Birleşir?"
description: "Mikro ERP veritabanında 490+ tablonun ilişkilerini ve doğru JOIN kullanımını öğrenin. 10 temel tablo, 12 JOIN kalıbı ve 3 hazır çoklu JOIN sorgusu."
date: 2026-05-25
category: mikro-erp
tags: ["mikro-erp", "sql-server", "tablo", "veritabani", "sql", "astaflow"]
url: https://mikroerp.dev/blog/mikro-erp-tablo-iliskileri-join-rehberi/
---

Mikro ERP veritabanı **490'dan fazla** tablo içerir. İlk kez bakan birisi bu tablolar arasında kaybolabilir: hangi tablo ne işe yarıyor, hangi alanla hangisi birleşiyor, `LEFT JOIN` mı `INNER JOIN` mi kullanmalı?

Bu rehberde Mikro ERP'nin **en çok kullanılan 10 tablosunu**, aralarındaki ilişkileri ve doğru JOIN kalıplarını tek bir yerde topladık. Blog'daki 20+ SQL yazımızın tamamı bu tablolar üzerine kurulu.

## Ana Tablolar — Mikro ERP'nin Omurgası

| Tablo | Prefix | Açıklama | Alan Sayısı |
|---|---|---|---|
| `CARI_HESAPLAR` | `cari_` | Müşteri, satıcı ve diğer cari kart bilgileri | 196 |
| `CARI_HESAP_HAREKETLERI` | `cha_` | Tüm cari hareketler (fatura, tahsilat, çek, senet, dekont...) | 185 |
| `STOKLAR` | `sto_` | Stok kart bilgileri (ürün tanımları) | 233 |
| `STOK_HAREKETLERI` | `sth_` | Tüm stok giriş/çıkış hareketleri | 148+ |
| `SIPARISLER` | `sip_` | Alış ve satış siparişleri | 139 |
| `DEPOLAR` | `dep_` | Depo tanımları ve bilgileri | 81 |
| `BANKALAR` | `ban_` | Banka hesap bilgileri | 98 |
| `KASALAR` | `kas_` | Kasa tanımları | 33 |
| `STOK_SATIS_FIYAT_LISTELERI` | `sfiyat_` | Stok satış fiyat listeleri | 36 |
| `E_FATURA_ISLEMLERI` | `efi_` | e-Fatura ve e-Arşiv işlemleri | 85 |

> **Prefix kuralı:** Mikro ERP'de her tablonun alanları bir prefix ile başlar. `cha_kod` → `cha_` prefixi → `CARI_HESAP_HAREKETLERI` tablosu. Bu kural, tablonun hangi alana ait olduğunu anında anlamanızı sağlar.

## İlişki Haritası — 12 Temel JOIN Kalıbı

### 1. Cari Kart ↔ Cari Hareket

```sql
CARI_HESAPLAR.cari_kod = CARI_HESAP_HAREKETLERI.cha_kod
```

**Ne yapar:** Cari hareketlere müşteri/satıcı ad ve ünvan bilgisini ekler.

**Ne zaman kullanılır:** Her zaman. Cari ekstre, tahsilat raporu, yaşlandırma — hemen her cari raporda bu JOIN gerekir.

```sql
SELECT
    CHA.cha_tarihi  AS [Tarih],
    CHA.cha_kod     AS [Cari Kodu],
    LTRIM(RTRIM(
        ISNULL(CH.cari_unvan1, '') + ' ' + ISNULL(CH.cari_unvan2, '')
    )) AS [Cari Ünvan],
    CHA.cha_meblag  AS [Tutar]
FROM dbo.CARI_HESAP_HAREKETLERI CHA WITH (NOLOCK)
LEFT JOIN dbo.CARI_HESAPLAR CH WITH (NOLOCK)
    ON CH.cari_kod = CHA.cha_kod
```

> **Neden LEFT JOIN?** Bazı hareketlerde cari kod hatalı girilmiş veya silinmiş olabilir. `INNER JOIN` kullanırsanız bu satırlar **kaybolur**. Cari ünvan gelmese bile hareketi görmek önemlidir.

---

### 2. Stok Kart ↔ Stok Hareket

```sql
STOKLAR.sto_kod = STOK_HAREKETLERI.sth_stok_kod
```

**Ne yapar:** Stok hareketlerine ürün adını ekler.

**Ne zaman kullanılır:** Stok bakiye raporu, satış raporu, maliyet analizi — stok hareketiyle çalışan her sorguda.

```sql
SELECT
    STH.sth_tarih       AS [Tarih],
    S.sto_isim           AS [Ürün Adı],
    STH.sth_miktar       AS [Miktar],
    STH.sth_tutar        AS [Tutar]
FROM dbo.STOK_HAREKETLERI STH WITH (NOLOCK)
INNER JOIN dbo.STOKLAR S WITH (NOLOCK)
    ON S.sto_kod = STH.sth_stok_kod
```

> **Burada INNER JOIN:** Stok kodu olmayan hareket normalde olamaz. Eğer varsa zaten hatalı veridir ve raporda gösterilmemesi mantıklıdır.

---

### 3. Stok Hareket ↔ Cari Kart

```sql
STOK_HAREKETLERI.sth_cari_kodu = CARI_HESAPLAR.cari_kod
```

**Ne yapar:** Stok çıkışında hangi müşteriye verildiğini, girişte hangi satıcıdan alındığını gösterir.

**Ne zaman kullanılır:** Satış raporu, alış-satış kâr analizi, müşteri bazlı stok hareketi.

```sql
SELECT
    S.sto_isim          AS [Ürün],
    CH.cari_unvan1      AS [Müşteri/Satıcı],
    STH.sth_miktar      AS [Miktar],
    STH.sth_tutar       AS [Tutar]
FROM dbo.STOK_HAREKETLERI STH WITH (NOLOCK)
INNER JOIN dbo.STOKLAR S WITH (NOLOCK)
    ON S.sto_kod = STH.sth_stok_kod
LEFT JOIN dbo.CARI_HESAPLAR CH WITH (NOLOCK)
    ON CH.cari_kod = STH.sth_cari_kodu
```

> **LEFT JOIN nedeni:** Depo transfer, sarf, fire gibi hareketlerde cari kodu boş olabilir.

---

### 4. Stok Hareket ↔ Depo (Giriş)

```sql
STOK_HAREKETLERI.sth_giris_depo_no = DEPOLAR.dep_no
```

**Ne yapar:** Stok girişinin **hangi depoya** yapıldığını gösterir.

---

### 5. Stok Hareket ↔ Depo (Çıkış)

```sql
STOK_HAREKETLERI.sth_cikis_depo_no = DEPOLAR.dep_no
```

**Ne yapar:** Stok çıkışının **hangi depodan** yapıldığını gösterir.

> ⚠️ **Dikkat:** Giriş ve çıkış deposu **farklı alanlardır**. Transfer hareketlerinde her ikisi de dolu olabilir. Aynı sorguya her iki depoyu da eklemek isterseniz:

```sql
LEFT JOIN dbo.DEPOLAR DG WITH (NOLOCK)
    ON DG.dep_no = STH.sth_giris_depo_no    -- Giriş deposu
LEFT JOIN dbo.DEPOLAR DC WITH (NOLOCK)
    ON DC.dep_no = STH.sth_cikis_depo_no    -- Çıkış deposu
```

**Her iki depo da aynı tablodur**, farklı alias ile ayrılır. Bu çok yapılan bir hatadır.

---

### 6. Sipariş ↔ Stok Kart

```sql
SIPARISLER.sip_stok_kod = STOKLAR.sto_kod
```

**Ne yapar:** Siparişlerdeki ürün koduna stok adını ekler.

---

### 7. Sipariş ↔ Cari (Müşteri)

```sql
SIPARISLER.sip_musteri_kod = CARI_HESAPLAR.cari_kod
```

**Ne yapar:** Siparişe müşteri bilgisini ekler. Satış siparişlerinde (`sip_tip = 0`) müşteri kodunu gösterir.

---

### 8. Sipariş ↔ Cari (Satıcı/Tedarikçi)

```sql
SIPARISLER.sip_satici_kod = CARI_HESAPLAR.cari_kod
```

**Ne yapar:** Alış siparişlerinde (`sip_tip = 1`) tedarikçi bilgisini ekler.

> **Aynı tablo, farklı alan:** Müşteri ve satıcı kodları ayrı alanlardır ama her ikisi de `CARI_HESAPLAR` tablosuna JOIN edilir:

```sql
LEFT JOIN dbo.CARI_HESAPLAR CM WITH (NOLOCK)
    ON CM.cari_kod = SIP.sip_musteri_kod      -- Müşteri
LEFT JOIN dbo.CARI_HESAPLAR CS WITH (NOLOCK)
    ON CS.cari_kod = SIP.sip_satici_kod       -- Satıcı/Tedarikçi
```

---

### 9. Fiyat Listesi ↔ Stok

```sql
STOK_SATIS_FIYAT_LISTELERI.sfiyat_stokkod = STOKLAR.sto_kod
```

**Ne yapar:** Fiyat listesindeki stok koduna ürün adını ekler. Birden fazla fiyat listesi olduğunda, listeleme ve karşılaştırma için kullanılır.

---

### 10. Sipariş ↔ Stok Hareket (GUID ile)

```sql
SIPARISLER.sip_Guid = STOK_HAREKETLERI.sth_siparis_uid
```

**Ne yapar:** Siparişin hangi stok hareketi (irsaliye/fatura) ile karşılandığını eşleştirir.

> **Önemli:** Bu ilişki `Uniqueidentifier` (GUID) tipindedir, string bazlı değildir. Performans açısından GUID JOIN'leri integer JOIN'lere göre daha yavaş olabilir, ancak Mikro'nun yapısında bu şekilde tasarlanmıştır.

**İlgili yazı:** [Fatura-Sipariş Eşleştirme SQL](/blog/mikro-erp-fatura-siparis-eslestirme-sql/)

---

### 11. Cari Hareket ↔ Stok Hareket (Evrak Bazında)

```sql
CARI_HESAP_HAREKETLERI.cha_evrakno_seri = STOK_HAREKETLERI.sth_evrakno_seri
AND CARI_HESAP_HAREKETLERI.cha_evrakno_sira = STOK_HAREKETLERI.sth_evrakno_sira
```

**Ne yapar:** Aynı faturanın cari tarafı (borç/alacak) ile stok tarafı (giriş/çıkış) eşleştirilir.

> ⚠️ **Dikkat:** Bu JOIN, seri+sıra numarası bazlıdır ve farklı evrak tipleri aynı seri/sıra numarasını kullanabilir. Güvenli kullanım için `cha_evrak_tip` filtresini de eklemeniz gerekir.

---

### 12. Cari Hareket ↔ Banka / Kasa

```sql
-- Karşı taraf banka ise:
CARI_HESAP_HAREKETLERI.cha_kasa_hizkod = BANKALAR.ban_kod
-- (cha_kasa_hizmet = 2 olduğunda)

-- Karşı taraf kasa ise:
CARI_HESAP_HAREKETLERI.cha_kasa_hizkod = KASALAR.kas_kod
-- (cha_kasa_hizmet = 4 olduğunda)
```

**Ne yapar:** Tahsilat veya ödeme hareketinde karşı tarafın hangi banka/kasa olduğunu gösterir.

> **`cha_kasa_hizmet` alanı:** 0=Cari, 2=Banka, 4=Kasa. Bu alana göre JOIN hedefi değişir. Doğrudan tek JOIN ile çözmek zordur, en pratik yolu CASE WHEN ile isim çekmektir.

---

## Sık Yapılan JOIN Hataları

### ❌ Hata 1: INNER JOIN ile Veri Kaybı

```sql
-- ❌ Cari kodu boş olan hareketler kaybolur:
INNER JOIN dbo.CARI_HESAPLAR CH ON CH.cari_kod = CHA.cha_kod

-- ✅ Cari kodu boş olan hareketler de görünür:
LEFT JOIN dbo.CARI_HESAPLAR CH ON CH.cari_kod = CHA.cha_kod
```

**Kural:** Ana tablonuzdaki (FROM'daki) her satırı görmek istiyorsanız **LEFT JOIN** kullanın. Sadece eşleşen satırları istiyorsanız **INNER JOIN** kullanın.

### ❌ Hata 2: Giriş-Çıkış Depo Karışıklığı

```sql
-- ❌ Satış raporunda giriş deposunu JOIN ettik — yanlış depo adı çıkar:
LEFT JOIN dbo.DEPOLAR D ON D.dep_no = STH.sth_giris_depo_no

-- ✅ Satış (çıkış) raporunda çıkış deposunu kullanmalıyız:
LEFT JOIN dbo.DEPOLAR D ON D.dep_no = STH.sth_cikis_depo_no
```

### ❌ Hata 3: String Alanlarda Boşluk Sorunu

Mikro ERP'de birçok string alanı sabit uzunlukta (NVARCHAR) olduğu için sağ tarafta boşluk kalabilir. Karşılaştırma ve birleştirme yaparken `LTRIM(RTRIM(...))` kullanın:

```sql
-- ❌ Sondaki boşluklar dahil:
SELECT cari_unvan1 + ' ' + cari_unvan2

-- ✅ Temizlenmiş:
LTRIM(RTRIM(ISNULL(cari_unvan1, '') + ' ' + ISNULL(cari_unvan2, '')))
```

### ❌ Hata 4: NOLOCK Kullanmamak

```sql
-- ❌ Canlı sistemde kilitleme riski:
FROM dbo.STOK_HAREKETLERI STH
INNER JOIN dbo.STOKLAR S ON S.sto_kod = STH.sth_stok_kod

-- ✅ Rapor sorgularında NOLOCK:
FROM dbo.STOK_HAREKETLERI STH WITH (NOLOCK)
INNER JOIN dbo.STOKLAR S WITH (NOLOCK) ON S.sto_kod = STH.sth_stok_kod
```

---

## 3 Hazır Çoklu JOIN Sorgusu

### Sorgu 1: Satış Faturası Detay Raporu (4 Tablo JOIN)

Stok hareket + stok kart + cari kart + çıkış deposu:

```sql
-- =============================================
-- Satış Faturası Detay Raporu
-- ⚙️ SSMS: Tarihleri değiştirin
-- ✅ Mikro: DECLARE satırlarını kaldırın
-- =============================================
DECLARE @P1 DATE = '2026-01-01';
DECLARE @P2 DATE = '2026-12-31';

SELECT
    STH.sth_tarih                AS [Fatura Tarihi],
    STH.sth_evrakno_seri         AS [Seri],
    STH.sth_evrakno_sira         AS [Sıra No],
    LTRIM(RTRIM(
        ISNULL(CH.cari_unvan1, '') + ' ' + ISNULL(CH.cari_unvan2, '')
    ))                           AS [Müşteri],
    S.sto_kod                    AS [Stok Kodu],
    S.sto_isim                   AS [Ürün Adı],
    DC.dep_adi                   AS [Çıkış Deposu],
    STH.sth_miktar               AS [Miktar],
    STH.sth_birim_pntr           AS [Birim],
    STH.sth_tutar                AS [Tutar],
    STH.sth_vergi                AS [KDV]
FROM dbo.STOK_HAREKETLERI STH WITH (NOLOCK)
INNER JOIN dbo.STOKLAR S WITH (NOLOCK)
    ON S.sto_kod = STH.sth_stok_kod
LEFT JOIN dbo.CARI_HESAPLAR CH WITH (NOLOCK)
    ON CH.cari_kod = STH.sth_cari_kodu
LEFT JOIN dbo.DEPOLAR DC WITH (NOLOCK)
    ON DC.dep_no = STH.sth_cikis_depo_no
WHERE STH.sth_tarih >= @P1
  AND STH.sth_tarih <= @P2
  AND STH.sth_evraktip = 4      -- Çıkış faturası
  AND STH.sth_tip = 1           -- Çıkış
  AND STH.sth_normal_iade = 0   -- Normal (iade değil)
ORDER BY STH.sth_tarih, STH.sth_evrakno_sira;
```

### Sorgu 2: Cari Ekstre Özet (2 Tablo JOIN)

Cari kart + cari hareket toplamı:

```sql
-- =============================================
-- Cari Bazlı Borç/Alacak Özet
-- =============================================
DECLARE @P1 DATE = '2026-01-01';
DECLARE @P2 DATE = '2026-12-31';

SELECT
    CHA.cha_kod                  AS [Cari Kodu],
    LTRIM(RTRIM(
        ISNULL(CH.cari_unvan1, '') + ' ' + ISNULL(CH.cari_unvan2, '')
    ))                           AS [Cari Ünvan],
    SUM(CASE WHEN CHA.cha_tip = 0 THEN CHA.cha_meblag ELSE 0 END) AS [Borç],
    SUM(CASE WHEN CHA.cha_tip = 1 THEN CHA.cha_meblag ELSE 0 END) AS [Alacak],
    SUM(CASE WHEN CHA.cha_tip = 0 THEN CHA.cha_meblag ELSE 0 END)
  - SUM(CASE WHEN CHA.cha_tip = 1 THEN CHA.cha_meblag ELSE 0 END) AS [Bakiye]
FROM dbo.CARI_HESAP_HAREKETLERI CHA WITH (NOLOCK)
LEFT JOIN dbo.CARI_HESAPLAR CH WITH (NOLOCK)
    ON CH.cari_kod = CHA.cha_kod
WHERE CHA.cha_tarihi >= @P1
  AND CHA.cha_tarihi <= @P2
GROUP BY CHA.cha_kod, CH.cari_unvan1, CH.cari_unvan2
HAVING SUM(CASE WHEN CHA.cha_tip = 0 THEN CHA.cha_meblag ELSE 0 END)
     - SUM(CASE WHEN CHA.cha_tip = 1 THEN CHA.cha_meblag ELSE 0 END) <> 0
ORDER BY [Bakiye] DESC;
```

### Sorgu 3: Sipariş Teslimat Durumu (3 Tablo JOIN)

Sipariş + stok kart + müşteri:

```sql
-- =============================================
-- Açık Sipariş ve Teslimat Durumu
-- =============================================
SELECT
    SIP.sip_tarih                AS [Sipariş Tarihi],
    SIP.sip_evrakno_seri         AS [Seri],
    SIP.sip_evrakno_sira         AS [Sıra No],
    LTRIM(RTRIM(
        ISNULL(CH.cari_unvan1, '') + ' ' + ISNULL(CH.cari_unvan2, '')
    ))                           AS [Müşteri],
    S.sto_isim                   AS [Ürün],
    SIP.sip_miktar               AS [Sipariş Miktarı],
    SIP.sip_teslim_miktar        AS [Teslim Edilen],
    SIP.sip_miktar - SIP.sip_teslim_miktar AS [Kalan],
    CASE
        WHEN SIP.sip_teslim_miktar >= SIP.sip_miktar THEN 'Tamamlandı'
        WHEN SIP.sip_teslim_miktar > 0 THEN 'Kısmi Teslim'
        ELSE 'Bekliyor'
    END AS [Durum]
FROM dbo.SIPARISLER SIP WITH (NOLOCK)
INNER JOIN dbo.STOKLAR S WITH (NOLOCK)
    ON S.sto_kod = SIP.sip_stok_kod
LEFT JOIN dbo.CARI_HESAPLAR CH WITH (NOLOCK)
    ON CH.cari_kod = SIP.sip_musteri_kod
WHERE SIP.sip_tip = 0              -- Satış siparişi (talep)
  AND SIP.sip_teslim_miktar < SIP.sip_miktar  -- Henüz tamamlanmamış
ORDER BY SIP.sip_tarih;
```

## Bu Bilgiyi Nereden Biliyoruz? (Kaynaklar)

*   **AstaFlow Case Study:** [Stok, Sipariş ve Finans Modülleri](/case-study/) — 8 şubeli Mikro ERP entegrasyonu
*   **Mikro ERP API Docs:**
    - [CARI_HESAPLAR](https://apidocs.mikro.com.tr/tablo-alan-adlari/cari_hesaplar) (196 alan)
    - [CARI_HESAP_HAREKETLERI](https://apidocs.mikro.com.tr/tablo-alan-adlari/cari_hesap_hareketleri) (185 alan)
    - [STOKLAR](https://apidocs.mikro.com.tr/tablo-alan-adlari/stoklar) (233 alan)
    - [STOK_HAREKETLERI](https://apidocs.mikro.com.tr/tablo-alan-adlari/stok_hareketleri) (148 alan)
    - [SIPARISLER](https://apidocs.mikro.com.tr/tablo-alan-adlari/siparisler) (139 alan)
*   **İlgili Araç:** [ERD Görselleştirici](/araclar/erd-gorselleştirici/) — Tablo ilişkilerini görsel olarak keşfedin
*   **İlgili Araç:** [SQL JOIN Jeneratörü](/araclar/sql-join-generator/) — Tablo seç → JOIN kodunu oluştur
*   **İlgili Yazılar:**
    - [Cari Ekstre Raporu](/blog/mikro-erp-cari-ekstre-raporu-sql/)
    - [Depo Bazlı Stok Bakiye](/blog/mikro-erp-depo-bazli-stok-bakiye-sql/)
    - [Satış Raporu SQL](/blog/mikro-erp-satis-raporu-sql/)
    - [Açık Sipariş Raporu](/blog/mikro-erp-acik-siparis-teslimat-raporu-sql/)
    - [Menü Sorgu Yönetimi Rehberi](/blog/mikro-erp-menu-sorgu-yonetimi-rehberi/)