Tarih ve Saat Verileriyle Çalışmak – Bölüm 21
SQL Server’da veri türleriyle çalışırken tarih ve saat verileri çokça kullanılmaktadır. Bu bölümde tarih ve saat verilerini kaydetmek için hangi veri türlerinin kullanıldığını öğreneceğiz. Tarih ve saat verilerinin nasıl girildiğini, SQL Server tarafından düzgün bir şekilde nasıl ayrıştırıldıklarını tarih ve saatlerin ve built-in fonksiyonlar tarafından nasıl manipüle edildiğini göreceğiz.
Tarih ve Saat Veri Türleri
SQL Server’ın her yeni sürümüyle geçici verilerin işlenişi hakkında ilerleme kaydedilmektedir. SQL Server 2016’da sorgu yazarken bile eski SQL Server sürümleri için oluşturulan verilerle çalışmanız gerekebileceğinden tarih ve saat verileri için geçmiş sürüm desteğini incelemeniz yararlı olacaktır:
- SQL Server 2008’den önce tarih ve saat verileri için sadece iki veri türü vardı: datetime ve smalldatetime. Bunların her biri hem tarihi hem de saati tek bir değerde saklar. Örneğin 12 Şubat 2014 saat 08:30 tarihini temsil etmek için ‘20140212 08:30:00’ şeklinde depolanabilir.
- SQL Server 2008’de, Microsoft dört yeni veri türü tanıttı: datetime2, date, time ve datetimeoffset. Bunlar hassasiyet, kapasite, zaman dilimi ve tarihleri zamandan ayırma işlevi olan fonksiyonlarıdır. Daha sonra oluşturacağınız projelerde, Microsoft tarafından yeni veri türlerinin kullanımı önerilmektedir.
- SQL Server 2012 ile Microsoft, tarih ve saat veri türlerinden kısmi verilerle (DATEFROMPARTS gibi) çalışmak ve tarih (EOMONTH gibi) hesaplamaları yapmak için yeni fonksiyonlar getirmiştir.
String Kullanarak Tarih ve Saat Veri Türlerini Girme
Sorgularınızda tarih ve saat verilerini kullanabilmek için tarih ve saati T-SQL’de gösterebilmemiz gerekir. SQL Server, tarih ve saatleri direkt literal değerler olarak girmenin yollarını sunmaz; bu nedenle SQL Server’daki diğer tüm stringler gibi, tek tırnaklı karakterlerle (genellikle string literals olarak adlandırılır) kullanılır. SQL Server kendisi string literal’leri açıkça tarih ve saat değerlerine dönüştürür. (Ayrıca string literal’leri, sonraki bölümlerde öğreneceğimiz T-SQL CAST ve CONVERT fonksiyonlarıyla explicit olarak dönüştürebilirsiniz.)
SQL Server çok çeşitli string literal biçimlerini tarih olarak yorumlayabilir, ancak tutarlılık, dil ve uyruk değerlerinin yorumlandırılmasıyla ilgili sorunlarla karşılaşmamak için ‘YYYYMMDD’ gibi bir biçim kullanmanız önerilir. Mesela 12 Şubat 2014’ü temsil etmek için ‘20140212’ değerini kullanabilirsiniz.
Bu örnekte string kullanarak 25 Ağustos 2007 tarihli siparişlere sorgu atılmıştır:
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate = '20070825';
Dilden bağımsız çeşitli tarih ve saat biçimleri de vardır:
Veri Tipi | Dildeki formatı | Örnek |
datetime |
‘YYYYMMDD hh:mm:ss.nnn’ ‘YYYY-MMDDThh:mm:ss.nnn’ ‘YYYYMMDD’ |
‘20140212 12:30:15.123’ ‘2014-02-12T12:30:15.123’ ‘20140212’ |
smalldatetime |
‘YYYYMMDD hh:mm’ ‘YYYY-MM-DDThh:mm’ ‘YYYYMMDD’ |
‘20140212 12:30’ ‘2014-02-12T12:30’ ‘20140212’ |
datetime2 |
‘YYYY-MM-DD’ ‘YYYYMMDD hh:mm:ss.nnnnnnn’ ‘YYYY-MM-DD hh:mm:ss.nnnnnnn’ ‘YYYY-MM DDThh:mm:ss.nnnnnnn’ ‘YYYYMMDD’ ‘YYYY-MM-DD’ |
‘20140212 12:30’ ‘2014-02-12T12:30’ ‘20140212”2014-02-12’ ‘20140212 12:30:15.1234567’ ‘2014-02-12 12:30:15.1234567’ ‘2014-02-12T12:30:15.1234567’ ‘20140212’ ‘2014-02-12’ |
date |
‘YYYYMMDD’ ‘YYYY-MM-DD’ |
‘20140212’ ‘2014-02-12’ |
time | ‘hh:mm:ss.nnnnnnn’ | 12:30:15.1234567′ |
Tarih ve Zamanla Ayrı Ayrı Çalışmak
Öğrendiğimiz üzere, SQL Server’da bazı geçici veri türleri hem tarihi hem de saati birlikte bir değerde depolamaktadır. datetime ve datetime2 yıl, ay, gün, saat, dakika, saniye ve daha fazlasını birleştirebilmektedir. datetimeoffset veri türü ayrıca tarih ve saate saat dilimi bilgisi ekler. Saat ve tarih bileşenleri, datetime2 gibi birleşik veri türlerinde isteğe bağlıdır. Bu nedenle bu veri türlerini kullanırken sadece kısmi veriler verildiğinde veri türlerinin nasıl davrandıklarının farkında olmamız gereklidir:
- Yalnızca tarih belirtilirse, veri türünün zaman kısmı sıfırlarla doldurulur ve saat gece yarısı olarak ayarlanmış sayılır.
Aşağıdaki örnekte yalnızca tarih bilgisi sağlandığında datetime2 davranışı gösterilmişitr:
DECLARE @DateOnly AS datetime2 = '20160112';
SELECT @DateOnly AS Result;
Dönen sonuç:
Result
----------------------------
2016-01-12 00:00:00.0000000
- Tarih ve saat (datetime veya datetime2 gibi) veri türleri yalnızca saat verileriyle doldurulursa, tarih kısmı 1 Ocak 1900 varsayılanı ayarlanır. Yalnızca saati kaydetmeniz gerekirse time veri türünü kullanın.
Aşağıdaki örnekte datetime2 veri türüne yalnızca saat verisi girildiğinde varsayılan tarihin atandığını gösterir:
DECLARE @time AS time = '12:34:56';
SELECT CAST(@time AS datetime2) AS Result;
Dönen sonuç:
Result
---------------------------
1900-01-01 12:34:56.0000000
Tarihi ve Saati Değerlerini Sorgulama
Tarih ve saat veri türlerini sorguda kullanırken beklediğiniz sonuçların dönmesi için hem tarihe hem de zaman dilimlerine dikkat etmeniz gereklidir.
Bu örnekte 25 Ağustos 2007 tarihli tüm satış siparişleri için sorgu çalıştırılıyor:
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate= '20070825';
Bu sorgu kullanıcının gereksinimlerini karşılayabilir. Aşağıda yalnızca 25 Ağustos 2007’de gece yarısı tarihli satış siparişlerinin döndürüldüğünü görüyoruz:
orderid custid empid orderdate
----------- ----------- ----------- -----------------------
10643 1 6 2007-08-25 00:00:00.000
10644 88 3 2007-08-25 00:00:00.000
Bunun nedeni, sorguda kullanılan ‘20070825’ string değerinin Sales.Orders.orderdate sütunu ile aynı veri türüne (datetime) dönüştürdüğü ve saat kısmına varsayılan olarak gece yarısı değerini uyguladığı içindir.
Sorgunun yorumlanması ise şu şekildedir:
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate= '20070825 00:00:00.000';
Burada yalnızca gece yarısı ile eşleşen değerlerin döndürüldüğü anlamına gelir. Tabloda 25 Ağustos 2007 tarihine ait siparişler bulunur ve gece yarısından sonraki bir saate kayıtlı bir satır varsa bunlar döndürülmez.
25 Ağustos 2007’ye ait kayıtların döndürülmesinden emin olmanın bir yolu, sipariş tarihi sütununun zaman kısmından bağımsız olarak, verileri tek bir değer yerine range ile sorgulamak olacaktır:
SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
WHERE orderdate >= '20070825'
AND orderdate < '20070826';
Tarih ve Saat Fonksiyonları
SQL Server, tarih ve saat verilerini manipüle etmek için tasarlanmış çeşitli fonksiyonlar sunar:
- Saat verisini eklemenin serbest olmasının yanında, geçerli tarih ve saati döndüren çeşitli return türleri arasında seçenekler sunan fonksiyonlar.
- Sorgunuzun gerektirdiği tarih ve saat değerlerinin sadece bir kısmını döndüren fonksiyonlar. DATENAME ve DATEPART fonksiyonların işlevselliği birbirine benzemektedir. Aralarındaki fark, dönen verinin tipidir.
- Ayrı olarak sağlanan yıl, ay ve gün gibi bileşenlerden tarih ve saat yazmış verileri döndüren işlevler. Bu olay zaten bu bölümde ele alındığı gibi, tarihlerin string literal olarak verilmesine alternatif sunmaktadır. Bu fonksiyonların, hedef tarih/saat verilerinin tüm bölümlerinin sağlanmasını gerektirdiğini unutmayın.
- Tarih ve saat değerlerini, artık tarihler de dahil olmak üzere ayın son gününü hesaplamak ve saat dilimi bilgisini değiştirmek için kullanılan fonksiyonlar.
- Tarih ve saat değerlerini, meta verileri döndüren veya input tarihleri arasındaki aralıklarla ilgili hesaplamaları yapan fonksiyonlar.
Kaynak:
Date and Time Types
Date and Time Data Types and Functions (Transact-SQL)