Para FLOAT'ta tutulmaz
FLOAT/REAL/DOUBLE ikili kayan noktalı sayılardır; 0,1 gibi değerleri tam saklayamazlar. Küçük farklar toplamlarda büyür ve = karşılaştırmaları şaşırtıcı sonuç verir.
SELECT CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT) AS toplam,
CASE WHEN CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT) = CAST(0.3 AS FLOAT) THEN 'eşit' ELSE 'eşit değil' END AS karsilastirma;
Tipi açıkça FLOAT yazdık, çünkü 0.1 gibi ondalık sabitler PostgreSQL, SQL Server, MySQL ve Oracle'da kesin türdedir: orada 0.1 + 0.2 = 0.3 doğru çıkar. Sorun sütun ya da ifade kayan noktalı olduğunda başlar. Bu örnekteki eşitsizliği PostgreSQL'de gerçek motorda doğruladık. Bu uygulamanın motoru SQLite olduğu için burada sabitler de kayan noktalı çalışır; bu, taklidin bilinen sınırlarından biridir.
| İhtiyaç | Tip |
|---|---|
| Para, miktar, oran | DECIMAL(p,s) / NUMERIC(p,s) (SQL Server'da MONEY da var ama hesaplamada yuvarlama riski nedeniyle DECIMAL önerilir; BigQuery'de NUMERIC) |
| Ölçüm, bilimsel değer | FLOAT / DOUBLE PRECISION / FLOAT64 |
| Sayaç, kimlik | INT, büyükse BIGINT (SQL Server INT sınırı ≈ 2,1 milyar) |
| Evet/hayır | BIT (SQL Server), BOOLEAN (PostgreSQL, MySQL), BOOL (BigQuery); Oracle'da 23ai öncesi NUMBER(1) |
ABS(a - b) < 0.0001. Raporlarda yuvarlamayı en sonda yap.Metin: uzunluk ve Unicode
- SQL Server:
VARCHARtek baytlık kod sayfası,NVARCHARUnicode. Türkçe karakterler içinNVARCHARve sabitlerdeN'İstanbul'kullan; aksi halde “ş, ğ, İ” soru işaretine dönebilir (UTF-8 collation'lı VARCHAR da bir seçenektir, SQL Server 2019+). - PostgreSQL:
TEXTveVARCHAR(n)aynı performanstadır; veritabanı UTF-8 ise sorun yoktur. - MySQL:
utf8mb4karakter kümesi kullan (eskiutf8emojileri saklayamaz). - Oracle:
VARCHAR2(n CHAR); bayt ve karakter uzunluğu farkına dikkat (VARCHAR2(10 BYTE)Türkçe karakterlerle 10 harf almayabilir).
SELECT name, LENGTH(name) AS karakter FROM products WHERE name LIKE '%ş%' OR name LIKE '%ğ%' OR name LIKE '%ı%';
Tarih ve saat tipleri
| Yalnız tarih | Tarih + saat (bölgesiz) | Saat dilimli an | |
|---|---|---|---|
| SQL Server | DATE | DATETIME2 (DATETIME eski) | DATETIMEOFFSET |
| PostgreSQL | DATE | TIMESTAMP | TIMESTAMPTZ (UTC saklar, oturumun saat diliminde gösterir) |
| MySQL | DATE | DATETIME | TIMESTAMP (UTC'ye çevirip saklar) |
| Oracle | DATE (saat de içerir!) | TIMESTAMP | TIMESTAMP WITH TIME ZONE |
| BigQuery | DATE | DATETIME | TIMESTAMP (her zaman UTC an) |
Saat dilimleri
Altın kural: anları UTC olarak sakla, kullanıcıya gösterirken yerel saate çevir. Türkiye 2016'dan beri yaz-kış saati uygulamadan UTC+3'tür ama müşterilerin veya sunucuların başka bölgelerde olabileceğini unutma.
-- SQL Server
SELECT CAST('2024-11-29 21:30:00' AS DATETIME2) AT TIME ZONE 'UTC' AT TIME ZONE 'Turkey Standard Time' AS istanbul;
SELECT SYSUTCDATETIME() AS utc_simdi, SYSDATETIMEOFFSET() AS yerel_simdi;
-- PostgreSQL
SELECT TIMESTAMPTZ '2024-11-29 21:30:00+00' AT TIME ZONE 'Europe/Istanbul' AS istanbul;
SET TIME ZONE 'Europe/Istanbul';
-- MySQL (saat dilimi tabloları yüklüyse)
SELECT CONVERT_TZ('2024-11-29 21:30:00', 'UTC', 'Europe/Istanbul');
-- Oracle
SELECT FROM_TZ(TIMESTAMP '2024-11-29 21:30:00', 'UTC') AT TIME ZONE 'Europe/Istanbul' FROM dual;
-- BigQuery
SELECT DATETIME(TIMESTAMP '2024-11-29 21:30:00+00', 'Europe/Istanbul') AS istanbul;
DATE(event_time) alırsan, Türkiye için 00:00–03:00 arasındaki olaylar bir önceki güne yazılır.Bu uygulamadaki web_events.event_time değerlerini UTC kabul edip İstanbul saatine çevirelim (+3 saat):
SELECT event_time AS utc,
datetime(event_time, '+3 hours') AS istanbul,
date(event_time) AS utc_gun,
date(datetime(event_time, '+3 hours')) AS istanbul_gun
FROM web_events
WHERE strftime('%H', event_time) IN ('21', '22', '23')
ORDER BY event_id
LIMIT 5;