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-15CAST 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-15Karakter 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
CASTevrenseldir (ANSI SQL standardı).CONVERTMySQL'e özeldir ve ek olarak karakter seti dönüşümü yapabilir. Taşınabilir kod içinCASTtercih et.
CAST Hedef Tipleri
| Hedef Tip | Açı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)) |
CHAR | String | CAST(42 AS CHAR) |
DATE | Tarih | CAST('2024-01-15' AS DATE) |
DATETIME | Tarih+Saat | CAST('2024-01-15 14:30' AS DATETIME) |
TIME | Saat | CAST('14:30:00' AS TIME) |
BINARY | Binary | CAST('abc' AS BINARY) |
JSON | JSON (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.5Gerç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
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.CAST ile yuvarlama beklemek:
CAST(3.99 AS SIGNED)= 3, yuvarlamaz. Yuvarlama istiyorsan önceROUNDkullan.FLOAT → DECIMAL dönüşümünde hassasiyet kaybı: FLOAT zaten yaklaşık değer taşır, DECIMAL'a çevirsen bile orijinal hata kalır.
Geçersiz tarih dönüşümü:
CAST('31/01/2024' AS DATE)çalışmaz çünkü format uyumsuz.STR_TO_DATEkullan.
Ö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
CASTyuvarlama yapmaz, keser — yuvarlama istiyorsanROUNDkullanPara hesaplarında FLOAT → DECIMAL dönüşümü dikkat gerektirir
CSV import gibi senaryolarda
CASTveSTR_TO_DATEbirlikte kullanılırImplicit casting index kullanımını engelleyebilir — performans etkisi
Taşınabilir kod için
CASTtercih et
AI Asistan
Sorularını yanıtlamaya hazır