Mikro ERP Tablo İlişkileri ve JOIN Rehberi: Hangi Tablo Hangisiyle Birleşir?
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.
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_HAREKETLERItablosu. 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
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.
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 JOINkullanırsanız bu satırlar kaybolur. Cari ünvan gelmese bile hareketi görmek önemlidir.
2. Stok Kart ↔ Stok Hareket
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.
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
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.
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ş)
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ış)
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:
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
SIPARISLER.sip_stok_kod = STOKLAR.sto_kod
Ne yapar: Siparişlerdeki ürün koduna stok adını ekler.
7. Sipariş ↔ Cari (Müşteri)
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)
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_HESAPLARtablosuna JOIN edilir:
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
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)
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
11. Cari Hareket ↔ Stok Hareket (Evrak Bazında)
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_tipfiltresini de eklemeniz gerekir.
12. Cari Hareket ↔ Banka / Kasa
-- 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_hizmetalanı: 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ı
-- ❌ 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ığı
-- ❌ 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:
-- ❌ Sondaki boşluklar dahil:
SELECT cari_unvan1 + ' ' + cari_unvan2
-- ✅ Temizlenmiş:
LTRIM(RTRIM(ISNULL(cari_unvan1, '') + ' ' + ISNULL(cari_unvan2, '')))
❌ Hata 4: NOLOCK Kullanmamak
-- ❌ 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:
-- =============================================
-- 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ı:
-- =============================================
-- 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:
-- =============================================
-- 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 — 8 şubeli Mikro ERP entegrasyonu
- Mikro ERP API Docs:
- CARI_HESAPLAR (196 alan)
- CARI_HESAP_HAREKETLERI (185 alan)
- STOKLAR (233 alan)
- STOK_HAREKETLERI (148 alan)
- SIPARISLER (139 alan)
- İlgili Araç: ERD Görselleştirici — Tablo ilişkilerini görsel olarak keşfedin
- İlgili Araç: SQL JOIN Jeneratörü — Tablo seç → JOIN kodunu oluştur
- İlgili Yazılar: