SQL Server’da yapacağımız aramalar, herhangi özel bir ayar uygulamamışsak default olarak case insensitive çalışır yani kayıtlar üzerinde arama yaparken değerler, büyük-küçük harf duyarlı değildir. Bu yüzden SQL Server üzerinde SELECT . FROM .. WHERE UserPwd=’abc’ ile SELECT . FROM .. WHERE UserPwd=’ABC’ ifadesi aynı sonucu getirir. Özellikle kullanıcı ile ilgili güvenlik bilgilerinin sorgulandığı durumlarda işlemlerin büyük-küçük harf duyarlı olmasına ihtiyaç duyabiliriz. Bunu sağlamanın birkaç yöntemi bulunmaktadır. Burada en çok kullanılan yöntemleri örneklendirmeye çalışacağız.
SQL Serverin, değerleri sıralama düzeni(sort order), SQL 2000 ile birlikte collation olarak tanımlanır. Daha önce yazdığımız bir yazıda SQL Server’daki collation ve language tanımlarıyla ilgili detaylı bilgi alabilirsiniz.
SQL Server’i kurarken eğer sistemin collation değerini değiştirmezsek case insensitive collation olarak kurulur. SQL Server’in güzel yanlarından biri de tüm sistemin collation değerini değiştirmek yerine sadece bir tablonun belli kolonu için collation ayarlaması yaptırmasıdır. Örneğin kullanıcı güvenlik bilgilerinin tutulduğu tablodaki şifre kolonu bu şekilde set edilebilir.
1.Yöntem
Bilindiği gibi “A” ve “a” değerleri, günlük konuşma ve yazmada aynı değerler gibi görünsede işlemci tarafından farklı değerler olarak yorumlanır. CPU sadece 1 ve 0’lardan oluşan ikili sistemden (binary) anladığı için bir karakteri yazıldığı gibi değil onu binary koda çevirerek işler. “Bütün karakterlerin binary kodları birbirinden farklı olduğu için SQL Server’a bir değer gönderdiğimiz zaman onu olduğu gibi değil binary koda çevirerek yorumlanmasını sağlarsak büyük-küçük harf duyarlılığı oluşturmuş oluruz. Bunu yapmanın yolu da SQL Server’da CAST fonksiyonunu kullanarak karşılaştırılacak değerleri binary veya varbinary veri tipine dönüştürmektir. Member tablosu ve içerisinde MemberPwd isimli bir kolonun olduğunu düşünelim. Bu kolonda “abc” ve “ABC” değerlerinin olduğunu varsayarak aşağıdaki sorguları çalıştıralım.
DECLARE @GonderilenSifre varchar(10) SET @GonderilenSifre='abc' SELECT * FROM Member WHERE MemberPwd='abc'
Bu sorgunun sonucunda hem “abc” hem de “ABC” şifresine sahip üyeler gelir. Oysa biz sadece küçük harflerle yazılmış “abc” şifresini arıyoruz. Kodumuzu aşağıdaki gibi düzeltirsek istediğimiz sonuca varırız.
DECLARE @GonderilenSifre varchar(10) SET @GonderilenSifre='abc' SELECT * FROM Member WHERE CAST(MemberPwd as binary)=CAST(@GonderilenSifre as binary)
Gerçekten de örnek olarak “abc” ve “ABC” değerleri üzerinde gidecek olursak ikisinin binary kodunun farklı olduğunu görürüz.
SELECT CAST('abc' as varbinary)--0x616263 SELECT CAST('ABC' as varbinary)--0x414243
Burada vyaskn.tripod.com’da okuduğum, dikkate alınması gereken bir not var. Eğer MemberPwd tablosunda herhangi bir index varsa CAST işleminin olduğu Query’de sözkonusu index kullanılmayacak ve Table Scan işlemi yapılacaktır. Bu da istenmeyen bir durum olduğu için Query Optimizer’ın (QP) indexi kullanabilmesi için kolonu bu şekilde sadece CAST fonksiyonu içerisinde değil ayrıca olduğu gibi belirtmemizin faydası olacaktır. Querymizi aşağıdaki gibi düzeltelim.
DECLARE @GonderilenSifre varchar(10) SET @GonderilenSifre='abc' SELECT * FROM Member WHERE CAST(MemberPwd as binary)=CAST(@GonderilenSifre as binary) AND MemberPwd = @GonderilenSifre
2.Yöntem
İkinci yöntem olarak daha önce yazdığımız COLLATE ifadesini kullanabiliriz. COLLATE ifadesi, verdiğimizin değerin SQL SERVER tarafından belirtilmiş collation türünde yorumlanmasını sağlar. Collation mekanizması, büyük veya küçük karakter setini ayrı ayrı içerdiği için query esnasında dilimize uygun olarak ilgili collation tipini belirtmemiz de bizi amacına ulaştırır. SQL_Latin1_General_CP1254_CI_AS collation serisi Türkçe karakter setinin de bulunduğu gibi değerlerin case-insensitive durumunu temsil eder. Sorgularda bunun case-sensitive türünü kullanacağız(SQL_Latin1_General_CP1254_CS_AS). SQL Server’in default collation değerini okumak için sp_helpsort prosedürü kullanılabilir.
DECLARE @GonderilenSifre varchar(10) SET @GonderilenSifre='abc' SELECT * FROM Member WHERE MemberPwd Collate SQL_Latin1_General_CP1254_CS_AS = @GonderilenSifre AND MemberPwd =@GonderilenSifre --INDEX kullanması için
3.Yöntem
SQL Server’da önceki yöntemlerden farklı olarak BINARY_CHECKSUM fonksiyonuyla da bu iş yapılabilmektedir. Ancak uzmanlar bunun doğru bir yöntem olmadığını, her zaman doğru sonucu vermeyeceğini ifade etmiştir.
Üçüncü yöntem olarak bu işi SQL Server’da değil business logic katmanında halledebiliriz. SQL Server’dan klasik yöntemle uyuşan şifreleri çektikten sonra uygulamamızı geliştirdiğimiz dilin(C#, VB.NET, Delphi . . .) fonksiyonlarını kullanarak büyük-küçük harf uyumluluğunu kontrol edebiliriz. Hatta bazı programlama dilleri default olarak case sensitive karşılaştırma yapmaktadır.
Teşekkürler, emeğine sağlık.
abı cok tesekkur ederım bole bı gırısımde bulundugun ıcın.faydalı olur sanırım artık bizler için yenıden çok tesekkürler
Çok teşekkürler verdiğiniz faydalı bilgile için çalışmalarınızın başarınızın devamını dilerim
hocam sana ne kadar teşekkür etsem azdır,bu bilgiye ulaşabilmek için saatlerdir araştırma yapıyorum gerçekten teşekkürler.