← Kursa Dön
📄 Text · 25 min

Tür Dönüşüm: CAST ve CONVERT

Giriş — Veri Tipleri Arasında Geçiş

Bazen bir değerin tipini değiştirmen gerekir: string'i sayıya, sayıyı tarihe, tarihi string'e çevirmek gibi. SQL'de bunu CAST ve CONVERT fonksiyonlarıyla yaparsın.

Peki neden veri tipi dönüşümü gerekir? Birkaç senaryo: CSV dosyasından import edilen veriler hep string gelir, farklı tablolardaki sütunlar farklı tipte olabilir, veya raporlarda fiyatı metin formatında göstermek isteyebilirsin.

🎯 Analoji: Tür dönüşümü, bir para birimini başka bir birime çevirmek gibi. 100 Dolar'ı Euro'ya çevirirsin — değer aynı ama format değişir. Ama dikkat et: her dönüşüm kayıpsız olmayabilir.


Implicit Casting — Otomatik Dönüşüm

MySQL birçok durumda otomatik tür dönüşümü yapar:

-- String → Sayı (otomatik)
SELECT '10' + 5;              -- 15 (string sayıya çevrildi)
SELECT '3.14' * 2;            -- 6.28

-- Sayı → String (otomatik, CONCAT'te)
SELECT CONCAT('Fiyat: ', 100);  -- "Fiyat: 100"

-- String → Date (otomatik, uygun format)
SELECT * FROM orders WHERE order_date > '2024-01-01';
-- '2024-01-01' string'i otomatik olarak DATE'e çevrildi

⚠️ Dikkat: Otomatik dönüşüme güvenme — beklenmedik sonuçlar verebilir: ``sql SELECT '10abc' + 5; -- 15 (MySQL '10abc'den 10'u çıkardı!) SELECT 'abc' + 5; -- 5 (MySQL 'abc'yi 0'a çevirdi!) SELECT 0 = 'abc'; -- 1 (TRUE! Çünkü 'abc' → 0) ``


CAST — Explicit Tür Dönüşümü

CAST(değer AS hedef_tip)

String ↔ Sayı

-- String → Integer
SELECT CAST('42' AS SIGNED);         -- 42
SELECT CAST('42' AS UNSIGNED);       -- 42

-- String → Decimal
SELECT CAST('3.14' AS DECIMAL(10,2));  -- 3.14

-- Sayı → String (CHAR)
SELECT CAST(42 AS CHAR);              -- "42"
SELECT CAST(3.14 AS CHAR);            -- "3.14"

String ↔ Tarih

-- String → Date
SELECT CAST('2024-01-15' AS DATE);           -- 2024-01-15
SELECT CAST('2024-01-15 14:30' AS DATETIME); -- 2024-01-15 14:30:00

-- Date → String
SELECT CAST(CURDATE() AS CHAR);              -- "2024-01-15"

Sayı ↔ Tarih (dikkat!)

-- Sayı → Date (dolaylı)
SELECT CAST(20240115 AS DATE);   -- Çalışmaz! Doğrudan dönüşüm yok
-- Çözüm:
SELECT CAST(CAST(20240115 AS CHAR) AS DATE);  -- 2024-01-15
-- Veya:
SELECT STR_TO_DATE('20240115', '%Y%m%d');     -- 2024-01-15

CAST ile Karşılaştırma Sorunlarını Çözme

-- Sütun VARCHAR ama sayısal karşılaştırma yapmak istiyoruz
-- postal_code VARCHAR ama sayısal sıralama istiyoruz
SELECT city, postal_code
FROM customers
ORDER BY CAST(postal_code AS UNSIGNED);
-- "1000" < "34000" < "35000" (sayısal sıra, string sırası değil)
-- String sırasında "1000" < "34000" < "35000" de doğru olur ama
-- "9000" > "35000" olurdu (string karşılaştırma ilk karaktere bakar)

CONVERT — MySQL'e Özel Dönüşüm

CONVERT iki farklı şekilde kullanılır:

Tür Dönüşümü (CAST ile aynı)

CONVERT(değer, hedef_tip)

SELECT CONVERT('42', SIGNED);           -- 42
SELECT CONVERT('3.14', DECIMAL(10,2));  -- 3.14
SELECT CONVERT(NOW(), DATE);            -- 2024-01-15

Karakter Seti Dönüşümü (CONVERT'in özel gücü)

CONVERT(değer USING karakter_seti)

-- UTF-8'e çevir
SELECT CONVERT('Merhaba' USING utf8mb4);

-- Latin1'den UTF-8'e
SELECT CONVERT(name USING utf8mb4) FROM old_table;

💡 İpucu: Tür dönüşümü için CAST evrenseldir (ANSI SQL standardı). CONVERT MySQL'e özeldir ve ek olarak karakter seti dönüşümü yapabilir. Taşınabilir kod için CAST tercih et.


CAST Hedef Tipleri

Hedef TipAçıklamaÖrnek
SIGNEDİşaretli tam sayıCAST('42' AS SIGNED)
UNSIGNEDİşaretsiz tam sayıCAST('42' AS UNSIGNED)
DECIMAL(M,D)Ondalık sayıCAST('3.14' AS DECIMAL(10,2))
CHARStringCAST(42 AS CHAR)
DATETarihCAST('2024-01-15' AS DATE)
DATETIMETarih+SaatCAST('2024-01-15 14:30' AS DATETIME)
TIMESaatCAST('14:30:00' AS TIME)
BINARYBinaryCAST('abc' AS BINARY)
JSONJSON (MySQL 5.7+)CAST('{"a":1}' AS JSON)

Dönüşüm Tuzakları

Veri Kaybı

-- Ondalık → Tam sayı: ondalık kısım kaybolur
SELECT CAST(3.99 AS SIGNED);    -- 3 (yuvarlamaz, keser!)

-- Yuvarlayarak dönüştürmek:
SELECT CAST(ROUND(3.99) AS SIGNED);  -- 4

-- Uzun string → Kısa CHAR: kırpılır
SELECT CAST('Çok uzun bir metin' AS CHAR(5));  -- "Çok u"

String → Sayı Dönüşüm Kuralları

SELECT CAST('123' AS SIGNED);      -- 123
SELECT CAST('123abc' AS SIGNED);   -- 123 (sayısal kısmı alır, uyarı verir)
SELECT CAST('abc' AS SIGNED);      -- 0 (sayıya çevrilemez, uyarı)
SELECT CAST('12.5' AS SIGNED);     -- 13 (yuvarlama!)
SELECT CAST('12.5' AS DECIMAL(10,1)); -- 12.5

Gerçek Dünya Örneği — Veri Import ve Formatlama

-- CSV'den gelen veriler hep VARCHAR — doğru tiplere çevir
CREATE TEMPORARY TABLE csv_import (
    id VARCHAR(20),
    name VARCHAR(200),
    price_str VARCHAR(20),
    date_str VARCHAR(20),
    quantity_str VARCHAR(20)
);

-- Import sonrası dönüşüm ve ana tabloya aktarım
INSERT INTO products (product_name, price, stock_quantity, created_at)
SELECT 
    name,
    CAST(REPLACE(price_str, ',', '.') AS DECIMAL(10,2)),
    CAST(quantity_str AS UNSIGNED),
    STR_TO_DATE(date_str, '%d/%m/%Y')
FROM csv_import
WHERE CAST(REPLACE(price_str, ',', '.') AS DECIMAL(10,2)) > 0;

Sıkça Yapılan Hatalar

  1. Implicit casting'e güvenmek: WHERE price = '19.99' çalışır ama tip uyumsuzluğu index kullanımını engelleyebilir. Explicit CAST veya doğru tip kullan.

  2. CAST ile yuvarlama beklemek: CAST(3.99 AS SIGNED) = 3, yuvarlamaz. Yuvarlama istiyorsan önce ROUND kullan.

  3. FLOAT → DECIMAL dönüşümünde hassasiyet kaybı: FLOAT zaten yaklaşık değer taşır, DECIMAL'a çevirsen bile orijinal hata kalır.

  4. Geçersiz tarih dönüşümü: CAST('31/01/2024' AS DATE) çalışmaz çünkü format uyumsuz. STR_TO_DATE kullan.


Özet

  • CAST(değer AS tip) — ANSI SQL standardı tür dönüşümü, evrensel

  • CONVERT(değer, tip) — MySQL'e özel, ek olarak karakter seti dönüşümü yapabilir

  • MySQL birçok durumda otomatik dönüşüm yapar ama buna güvenme

  • CAST yuvarlama yapmaz, keser — yuvarlama istiyorsan ROUND kullan

  • Para hesaplarında FLOAT → DECIMAL dönüşümü dikkat gerektirir

  • CSV import gibi senaryolarda CAST ve STR_TO_DATE birlikte kullanılır

  • Implicit casting index kullanımını engelleyebilir — performans etkisi

  • Taşınabilir kod için CAST tercih et