Veri tipi seçimi, tablo tasarımında en kolay atlanan ama sonradan değiştirilmesi en zor kararlardan biridir. Gerekenden geniş bir tip her satırda birkaç bayt fazla yer kaplar; bu fark milyonlarca satırda gigabaytlara, daha fazla okunan sayfaya, daha büyük index’lere ve daha uzun yedeklere dönüşür. Yanlış tip ise daha sinsi sorunlar yaratır: kuruşların kaybolduğu hesaplamalar, index’i kullanamayan sorgular, Türkçe karakterlerin bozulması.
Bu rehberde SQL Server’daki temel veri tiplerini, hangi durumda hangisinin seçileceğini ve en sık yapılan hataları anlatıyoruz.
Veri modelinizi gözden geçirmek mi istiyorsunuz?
Aryasoft, tablo ve veri tipi tasarımınızı performans, depolama ve veri doğruluğu açısından inceler.
Tam Sayılar
| Tip | Boyut | Aralık |
|---|---|---|
| tinyint | 1 bayt | 0 ile 255 |
| smallint | 2 bayt | -32.768 ile 32.767 |
| int | 4 bayt | yaklaşık ±2,1 milyar |
| bigint | 8 bayt | yaklaşık ±9,2 × 10^18 |
Değer aralığına uyan en küçük tipi seçin; ama büyümeyi de hesaba katın. Yoğun yazılan bir tablonun int IDENTITY kolonu 2,1 milyara ulaştığında insert’ler durur ve bigint’e geçiş büyük tablolarda saatler süren bir işlemdir. Hızla büyüyen log ve hareket tablolarında baştan bigint kullanmak daha güvenlidir.
Ondalık Sayılar ve Para
- decimal(p, s) / numeric: Kesin değer saklar. Para, miktar, oran gibi tüm finansal veriler için doğru seçimdir.
- float / real: Yaklaşık değer saklar. Bilimsel ölçümler için uygundur; para için kesinlikle uygun değildir.
- money / smallmoney: Sabit 4 ondalık basamakla saklar; çarpma ve bölmede yuvarlama sorunları yaşatabilir. decimal genellikle daha öngörülebilirdir.
Uyarı
Para tutarlarını float olarak saklamak, toplamlarda kuruş farklarına ve “0,1 + 0,2 = 0,30000000000000004” türünden sonuçlara yol açar. Muhasebe ve faturalama verilerinde her zaman decimal kullanın ve hassasiyeti (örneğin decimal(19, 4)) iş kurallarına göre belirleyin.
Metin: char, varchar, nchar, nvarchar
| Tip | Uzunluk | Karakter başına | Ne zaman |
|---|---|---|---|
| char(n) | Sabit | 1 bayt (tek baytlık kod sayfaları) | Hep aynı uzunlukta kodlar |
| varchar(n) | Değişken | 1 bayt; UTF-8 collation’da 1-4 bayt | Yalnızca collation’ın kod sayfasındaki karakterler |
| nchar(n) | Sabit | 2 bayt (UTF-16) | Sabit uzunlukta Unicode |
| nvarchar(n) | Değişken | 2 bayt, bazı karakterlerde 4 | Çok dilli ya da belirsiz içerik |
varchar, Turkish_CI_AS gibi bir collation ile Türkçe karakterleri saklayabilir; ancak kod sayfasında olmayan karakterler (başka alfabeler, emojiler) “?” olarak kaydedilir. Çok dilli veri ya da dışarıdan gelen serbest metin için nvarchar kullanın. SQL Server 2019 ve sonrasında _UTF8 ile biten collation’lar, varchar kolonlarında Unicode’u UTF-8 olarak saklamayı mümkün kılar. Collation seçimi için collation rehberimize bakın.
varchar(max) ve nvarchar(max) yalnızca 8.000 baytı (nvarchar’da 4.000 karakteri) aşabilecek veriler için kullanılmalıdır. Her kolonu max tanımlamak, index anahtarı olarak kullanılamamalarına ve bellek tahminlerinin şişmesine yol açar.
Tarih ve Saat
| Tip | Boyut | Hassasiyet | Not |
|---|---|---|---|
| date | 3 bayt | Gün | Yalnızca tarih gerekiyorsa |
| time(n) | 3-5 bayt | 100 nanosaniye | Yalnızca saat |
| datetime2(n) | 6-8 bayt | 100 nanosaniyeye kadar | Yeni tasarımlar için önerilen |
| datetimeoffset(n) | 8-10 bayt | 100 nanosaniye | Saat dilimi farkıyla birlikte |
| datetime | 8 bayt | ~3,33 milisaniye | Eski; yeni tasarımda datetime2 tercih edin |
| smalldatetime | 4 bayt | Dakika | Eski |
Yalnızca tarih gerekiyorsa date kullanın. Saat de gerekiyorsa datetime2, hem daha geniş aralığa hem de ayarlanabilir hassasiyete sahiptir. Farklı saat dilimlerinden veri geliyorsa datetimeoffset ya da UTC’de saklamak tutarlılık sağlar.
Diğer Önemli Tipler
- bit: Evet/hayır değerleri için; bir tablodaki en fazla 8 bit kolonu tek bir baytta saklanır.
- uniqueidentifier: 16 baytlık GUID. Rastgele GUID’leri clustered index anahtarı yapmak, sürekli sayfa bölünmesine ve parçalanmaya yol açar; gerekiyorsa
NEWSEQUENTIALID()ya da ayrı bir tam sayı anahtar kullanın. - varbinary(max): İkili veri. Büyük dosyaları veritabanında saklamak yedekleri ve restore süresini büyütür; çoğu zaman dosyayı dışarıda tutup yolunu saklamak daha iyidir.
- xml ve json: Yarı yapılandırılmış veri. SQL Server 2025 yerel
jsonveri tipini getirir; daha eski sürümlerde JSONnvarchariçinde saklanır. - vector: SQL Server 2025 ile gelen, gömme (embedding) vektörlerini saklamak ve benzerlik araması yapmak için tasarlanmış tip.
- text, ntext, image: Kullanımdan kaldırılmıştır; yerine
varchar(max),nvarchar(max)vevarbinary(max)kullanın.
Örtük Dönüşüm: Görünmeyen Performans Sorunu
Karşılaştırılan iki değerin tipi farklıysa, SQL Server birini diğerine dönüştürür. Dönüştürülen taraf index’li bir kolonsa, index seek yapılamaz ve tablo taranır. En klasik örnek, varchar bir kolonun nvarchar bir parametreyle karşılaştırılmasıdır:
-- MusteriKodu varchar(20) ve index'li
DECLARE @kod nvarchar(20) = N'M-1001';
-- Kolon nvarchar'a dönüştürülür; collation'a bağlı olarak index scan'e düşebilir
SELECT * FROM dbo.Musteri WHERE MusteriKodu = @kod;
-- Parametre kolonla aynı tipte: index seek
DECLARE @kod2 varchar(20) = 'M-1001';
SELECT * FROM dbo.Musteri WHERE MusteriKodu = @kod2;
Execution plan’da CONVERT_IMPLICIT uyarısı bu sorunun işaretidir. Uygulama tarafında parametre tiplerini kolon tipleriyle eşleştirmek (özellikle ORM’lerde string parametrelerin varsayılan olarak nvarchar gönderildiğini bilmek) bu tür sorunları kökten çözer. Aynı mantık join kolonları için de geçerlidir: birbirine join edilen kolonların tipleri aynı olmalıdır.
İpucu
Mevcut bir veritabanında tip uyumsuzluklarını bulmak için, aynı adı taşıyan kolonların farklı tablolarda farklı tiplerde tanımlanıp tanımlanmadığına bakın. Örneğin bir tabloda int, diğerinde varchar olan MusteriNo kolonları, join’lerde örtük dönüşümün ve yavaş sorguların sık rastlanan nedenidir.
SELECT c.name AS column_name,
COUNT(DISTINCT TYPE_NAME(c.user_type_id) + '(' + CAST(c.max_length AS varchar(10)) + ')') AS type_variants,
STRING_AGG(CONVERT(nvarchar(max), OBJECT_NAME(c.object_id) + ':' + TYPE_NAME(c.user_type_id)), ', ') AS usages
FROM sys.columns AS c
JOIN sys.tables AS t ON t.object_id = c.object_id
GROUP BY c.name
HAVING COUNT(DISTINCT TYPE_NAME(c.user_type_id) + '(' + CAST(c.max_length AS varchar(10)) + ')') > 1
ORDER BY type_variants DESC;
Kontrol Listesi
- Tam sayılarda değer aralığına ve büyümeye uygun tip seçildi.
- Para ve miktar verileri decimal; float yalnızca yaklaşık değerler için.
- Çok dilli metin nvarchar; max tipler yalnızca gerektiğinde.
- Yeni tasarımlarda datetime yerine date ya da datetime2.
- Rastgele GUID’ler clustered index anahtarı değil.
- text, ntext ve image kullanılmıyor.
- Join edilen kolonlar ve uygulama parametreleri kolon tipleriyle uyumlu.
İlgili Yazılar
SQL Server Danışmanlığı
Veri modelinizi sağlam temellere oturtun
Aryasoft’un kıdemli DBA ekibi tablo ve veri tipi tasarımınızı performans, depolama ve veri doğruluğu açısından inceler; örtük dönüşümleri ve tip uyumsuzluklarını bulup kesintisiz geçiş planlarıyla düzeltir.