Dönüşüm Fonksiyonları – Bölüm 26
T-SQL sorgularında veri dönüşümü işlemleri çok yaygındır. Bazen dönüşüm otomatik olarak gerçekleşir; bazen de sizin durumu ele almanız gerekir. Bu bölümde, çeşitli SQL Server fonksiyonlarını kullanarak verileri türler arasında explicit olarak dönüştürmeyi öğreneceğiz. Ayrıca dönüşüm işlemlerinde sorugunuza ekstra esneklik kazandıracak SQL Server fonksiyonlarıyla çalışmayı da öğreneceksiniz.
Implicit and Explicit Veri Tipi Dönüşümleri
İlk bölümlerde, SQL Server işlemleri sırasında veri türlerinin dönüştürüldüğü senaryolar olduğunu görmüştük. SQL Server’ın tür dönüştürme öncelik kurallarını izleyerek implicit olarak veri türlerini dönüştürebildiğini öğrendik. Ancak, tür önceliğini geçersiz kılmanız ya da bir implicit dönüşümün başarısız olabileceği bir işlemi zorlamanız gerekebilir.
Bunu yapmak için TRY_CONVERT fonksiyonuna ek olarak CAST ve CONVERT fonksiyonlarını da kullanabilirsiniz.
Veri türleri arasında dönüşüm işlemi yaparken dikkat edilmesi gereken bazı noktalar şunlardır:
Collation: CAST veya CONVERT, karakter string input verildiğinde output olarak da karakter string döndürdüğünde, output da aynı collation kullanır. Karakter türünden olmayan bir veriyi karaktere tipine dönüştürürken, döndürülen değer veri tabanı collation’ı kullanır. Bu davranışı geçersiz kılmak için CAST veya CONVERT ile birlikte COLLATE seçeneği kullanılabilir.
Truncation: Farklı veri türlerini karakter ya da binary türler arasında dönüştürdüğünüzde, veriler truncate edilebilir, veya böyle gözükebilir, veya sonuç görüntülenemeyecek kadar kısa olduğu için bir hata basılabilir. Sonuç ilgili veri türlerine bağlıdır. Örneğin, iki basamaklı bir integer’dan char(1) değerine dönüştürüldüğünde, “*”döndürülür. Bu, sonuçların görüntülenmek için çok küçük olduğu anlamını taşır.
CAST Dönüşümleri
SQL Server’da bir değeri, bir veri türünden diğerine dönüştürmek için CAST fonksiyonu kullanılır. CAST, ANSI standartlarında bir fonksiyondur ve bu nedenle bir sonraki bölümde öğreneceğimiz üzere, SQL Server’a özgü olan CONVERT fonksiyonuna tercih edilmesi önerilmektedir.
CAST skaler fonksiyon olduğundan, SELECT ve WHERE yan tümcelerinde kullanılabilir.
Aşağıda CAST fonksiyonunun nasıl kullanılacağı gösterilmektedir:
CAST(<value> AS <datatype>)
TSQL örnek veri tabanından alınan aşağıdaki örnekte, orderdate’i datetime’dan date’e dönüştürmek için CAST kullanmıştır:
SELECT orderid, orderdate AS order_datetime, CAST(orderdate AS DATE) AS order_date FROM Sales.Orders;
Dönen sonuç:
orderid order_datetime order_date
----------- ----------------------- ----------
10248 2006-07-04 00:00:00.000 2006-07-04
10249 2006-07-05 00:00:00.000 2006-07-05
10250 2006-07-08 00:00:00.000 2006-07-08
Bir tarihi sayısal bir değere dönüştürmeye çalışmak gibi uyumsuzluk durumunda, CAST fonksiyonu hata döndürecektir:
SELECT CAST(SYSDATETIME() AS int);
Dönen sonuç:
Msg 529, Level 16, State 2, Line 1 Explicit conversion from data type datetime2 to int is not allowed
CONVERT Dönüşümleri
CAST fonksiyonuna ek olarak, SQL Server’da CONVERT fonksiyonu bulunmaktadır. ANSI CAST fonksiyonundan farklı olarak, CONVERT fonksiyonu SQL Server’a özgüdür ve bu nedenle kullanımı önerilmez. Ancak, dönüş değerini biçimlendirebilme özelliği nedeniyle, zaman zaman CONVERT işlevini kullanmanız gerekebilir.
CAST gibi CONVERT de skaler bir fonksiyondur. CONVERT fonksiyonunun SELECT ve WHERE ifadelerinde kullanabilirsiniz.
Aşağıda CONVERT fonksiyonu kullanımı gösterilmektedir:
CONVERT(<datatype>, <value>, <optional_style_number>);
Stil numarası bağımsız değişkeni, CONVERT fonksiyonunun döndürülen verileri belirtilen seçenek kümesine göre biçimlendirmesine neden olur. Bunlar, sayısal, XML ve ikili veri stillerine ek olarak çok çeşitli tarih ve saat stillerini de kapsar. Bazı tarih ve saat örnekleri şunları içerir:
Yüzyıl olmadan Stil | Yüzyıl ile Stil | Standart Etiket | Değer |
1 | 101 | U.S | mm/dd/yyyy |
2 | 102 | ANSI | yy.mm.dd -yüzyıl için bir değişiklik yok |
12 | 112 | ISO | yymmdd veya yyyymmdd |
Aşağıdaki örnekte, geçerli saati datetime’dan char(8)’e dönüştürmek için CONVERT fonksiyonu kullanımı gösterilmiştir:
SELECT CONVERT(CHAR(8), CURRENT_TIMESTAMP, 12) AS ISO_short, CONVERT(CHAR(8), CURRENT_TIMESTAMP, 112) AS ISO_long;
Dönen sonuç:
ISO_short ISO_long
--------- --------
120212 20120212
PARSE Dönüşümleri
Çok yaygın bir iş problemine bir göz atalım. Genellikle birleştirilmiş bir şekilde, bir veya daha fazla string değerinden tarih, saat veya sayısal değer oluşturulmaktır. SQL Server PARSE işleviyle bu görevi kolaylaştırır.
PARSE fonksiyonu input olarak, SQL Server tarafından tarih, saat veya sayısal değer olarak algılanacak biçimde olan bir string değeri alır ve belirtilen veri türünde bir değer döndürür:
SELECT PARSE('<string_value>',<data_type>
[USING <culture_code>]);
Medeniyet parametresi, ABD İngilizcesi için “en-US”, İspanyolca için “es-ES” vb. gibi geçerli bir .NET Framework medeniyet kodu biçiminde olmalıdır. Medeniyet parametresi atlanırsa, geçerli kullanıcı oturumundaki ayarlar kullanılır.
Aşağıdaki örnekte, “02/12/2012” string değeri, en-US kodu kullanarak datetime2 biçimine dönüştürmüştür:
SELECT PARSE('02/12/2012' AS datetime2 USING 'en-US') AS us_result;
Dönen sonuç:
us_result
----------------------
2012-02-12 00:00:00.00
TRY_PARSE and TRY_CONVERT Dönüşümü
CONVERT veya PARSE kullanılırken, input değeri belirtilen output tipine dönüştürülemezse bir hata oluşabilir.
Örneğin, 31 Şubat 2012 (geçersiz bir tarih) CONVERT işlevine input olarak verilirse, runtime hatası ortaya çıkacaktır:
SELECT CONVERT(datetime2, '20120231');
Dönen sonuç:
--Msg 241, Level 16, State 1, Line 1 --Conversion failed when converting date and/or time from character string
SQL Server bununla başa çıkmak için dönüştürme fonksiyonları sağlar. TRY_PARSE ve TRY_CONVERT, sırasıyla PARSE ve CONVERT gibi bir dönüşüm işlevi dener. Ancak burada runtime hatası basmak yerine, başarısız dönüşüm işlemleri için NULL döndürülmektedir.
Aşağıdaki örneklerde PARSE ve TRY_PARSE davranışları karşılaştırılmaktadır. İlk olarak, PARSE fonksiyonu geçersiz bir tarihi dönüştürmeye çalışırmaktadır:
SELECT PARSE('20120231' AS datetime2 USING 'en-US')
Dönen sonuç:
Dönen sonuç:
------------------------
NULL