Stored Procedure'ler İle Neleri Yapmak Caizdir? 2 | yazilimgunlugu.com
Eklenme Tarihi: 13.5.2009 20:01:49
Bu makalede Stored Procedure'ler tablolarda nasıl kayıt arandığından söz edilmektedir.
Malumunuz olduğu üzere daha önce yazıp burada sizinle paylaştığım makalede Stored Procedure’ler ile hangi işlemleri yapmanın serbest, hangilerini yapmanın yasak olduğu sorusuna cevap aramaya çalışmıştım. O yazıda Stored Procedure’ler ile tablolara kayıt ekleme işleminden söz etmiştim. Şimdi benzer araştırmayı Stored Procedure’ler ile veri çekme hakkında yapacağız. Bakalım Stored Procedure'ler ile tablolardan veri çekmek serbest mi yoksa yasak mı?
Stored Procedure ile tablolardan veri çekme konusunda yapacağım araştırmanın hayali olmaması için işe Visual Studio 2003 bir C# uygulaması hazırlamakla başladım. Visual Studio 2005 ve 2008 varken neden Visual Studio 2003? Çünkü resmi kayıtlara geçen bilgilere göre Stored Procedure’leri kullanarak veritabanından veri çekme tekniğini Dünyada ilk kez 2003 yılında yerli bir programcılık yazarı akıl edip kullandı. Bu nedenle bu yazıyı bu tekniğin geliştirildiği şartları gözeterek yazmayı seçtim.
Visual Studio 2003 ile hazırlayacağım bu projede yapacağım düzenleme sonucu proje çalıştırıldığı zaman telefon numarası öğrenilmek istenen firmanın adı girilecek, telefon numarası Stored Procedure sayesinde ilgili tablodan okunup ekrana getirilecek. İşte ilgilendiğim tablodan veri çekerken kullanabileceğim Stored Procedure.
Bu Stored Procedure’yi yakından incelediğinizde "Par_giris" ve "Par_cikis" adında 2 parametreye sahip olduğunu görürsünüz. Par_cikis adlı parametrenin yönünün OutPut olduğunu fark etmiş olmalısınız. Çünkü bu 2 parametrenin ilki dışarıdan bilgi alıp ikinci parametre aracılığıyla başka bir bilgiyi geriye gönderecektir. Geriye değer gönderilirken kullanılacak parametrenin yönü Output olarak ayarlanmalıdır.
Bu Stored Procedure işletildiğinde kendisine “Par_giris” adını verdiğim parametre ile gönderilen bilgi WHERE deyimi sayesinde “Musteriler” tablosunda aranır. Tabloda öyle bir kayıt varsa “Telefon” alanın içeriği yönü Output olan “Par_cikis” adı verilen parametreye aktarılır. Daha sonra bu parametrenin içeriği istenildiği gibi kullanılabilir. Yaptığım araştırmalara göre 2004 yılının şartlarına göre bu bilgileri vermek yani bu şekilde Stored Procedure hazırlamak suç değildir, Stored Procedure'lerden bu şekilde yararlanıp veritabanından bir tek bilgi çekmek serbesttir.
Stored Procedure’u bu şekilde düzenledikten sonra Visual Studio penceresine geçip projenin formuna “Arama Yap” başlığına sahip bir düğme yerleştirdim. Sizler bu makalede yazılanları denerken nesne adı çalmış olmamak için forma yerleştirdiğiniz düğmeye ad seçerken bir argo sözlüğünden yararlanabilirsiniz. Örneğin düğmeye “Ara_dedik_lan” adını verebilirsiniz. Forma yerleştirdiğim düğme tıklandığı zaman işletilmesini istediğim Stored Procedure 2 parametreye sahip olduğu için 2 aşağıdaki gibi kod yazarak SqlParameter nesnesi hazırladım.
Parametre1 = new SqlParameter("@Par_giris", SqlDbType.Char, 20);
Parametre2 = new SqlParameter("@Par_cikis", SqlDbType.Char, 15);
2. parametre ile Stored Procedure’den bilgi alınacağı veya Stored Procedure'den bu parametre sayesinde dışarıya bilgi gönderileceği için Direction özelliğini “Output” olarak ayarladım. Ardından hazırladığım parametre nesnelerini Add() metodu ile SqlCommand nesnesinin Parameters koleksiyonuna ekledim. Ayrıca bu Stored Procedure’nin adını SqlCommand nesnesinin CommandText özelliğine aktardım. Telefon numarasını öğrenmek amacıyla hazırladığım kodun hepsini aşağıda verdim.
SqlCommand nesnesinin yönü input olan ilk parametresinin Value özelliğine bilgi aktarma işlemini Visual Basic kaynaklı InputBox() metodu ile yaptım. InputBox() metodu ile ekrana getirilen diyalog kutusuna tabloda aranacak firmanın adını yazdım.
SqlCommand nesnesinin “Parametre1” adı verilen ilk parametresine bilgi aktarılıp ExecuteNonQuery() metodu ile adı SqlCommand nesnesinin CommandText özelliğine adı aktarılan Stored Procedure işletilirse, Parametre1’in içeriği tablodaki “Ad” alanında aranır. WHERE (Ad = @Par_giris) şartı sağlanırsa aynı kaydın “Telefon” alanın içeriği SqlCommand nesnesinin Output tipindeki “Parametre2” adlı parametresine aktarılır. Tabloda aranılan kayıt yoksa parametreye boşluk aktarılır. Parametre2’nin içeriğini ekranda göstermek için MessageBox() metodunu kullandım.
Yukarıda verdiğim örnekte SqlCommand nesnesi Toolbox’tan yararlanılarak forma yerleştirildiği için formdaki bütün metotlarda kullanılabilir. Bu nedenle metottan çıkıldığında SqlCommand nesnesinin parametreleri yaşamaya devam eder ve “Arama Yap” başlığını verdiğim düğme 2. kez tıklanıp verdiğim kod tekrar işletildiğinde hata meydana gelir. Bu hatanın önüne geçmek yani parametrelerin mükerrer olmasını engellemek için metodun sonuna aşağıda verdiğim 2 satırı yazarak parametreleri Remove() metodu ile Parameters koleksiyonundan sildim.
İzninizle tam bu noktada bir değerlendirme yapalım: Yukarıda verdiğim Stored Procedure ile ne mi yaptım? Cevap: Bir nevi arama yaptım. “Musteriler” adı verdiğim tabloda firma adına göre arama yapıp firmanın kayıtlı telefonunu öğrendim. Öğrendiğim telefonu ise MessageBox ile ekrana getirdim. Yaptığım araştırmalara göre sizler yukarıda yaptığım işlemin benzerini gönül rahatlığıyla yapabilirsiniz. Çünkü Stored Procedure ile tablolardan veri çekme tekniğini geliştiren, yani bu buluşa imza atan yerli yazar Stored Procedure’nin OutPut tipinde bir tek parametreye sahip olmasına, dolayısıyla tablodan bir tek bilginin Stored Procedure’ler sayesinde çekilmesine bir itirazı yoktur.
Konunun iyice anlaşılmasını sağlamak için üzerinde çalıştığım projenin formuna 4 TextBox yerleştirdim. Kullanıcı ayrıntılarını görmek istediği kaydın veya firmanın adını ilk TextBox’a girecek. Aranacak kaydın “Ad” alanı formdaki ilk TextBox’a gerilip “Arama Yap” başlıklı düğme tıklandığı zaman kaydın ayrıntıları formdaki diğer TextBox’lara aktarılacak.
Başka bir deyişle bu kez Stored Procedure sayesinde veritabanından 1 değil tam 3 bilgi çekeceğim. Bu amaçla yukarıda verdiğim Stored Procedure’yi aşağıdaki gibi değiştirdim. Bu Stored Procedure 4 parametreye sahip olacak. İlk parametre dışarıdan bilgi alınırken kullanılacağı için yönü Input ve diğerlerinin yönü ise Output olacak.
Bu kısmı yazarken kullandığım “Musteriler” tablosu “Ad” alanına göre indekslendiği ve bu indekse Primary Key özelliğini verdiğim için “Ad” alanı aynı olan birden fazla kayıt tabloda olamaz. Bu nedenle WHERE (Ad=@Par_ad) karşılaştırması doğru ise “Adres” alanın içeriği yönü Output olan “@Par_adres” parametresine ve “Telefon” alanın içeriği ise “@Par_telefon” parametresine aktarılır.
Sizin yapmanız gereken, Output tipindeki bu parametrelerin içeriğini yakalamak amacıyla SqlCommand nesnesi için parametre tanımlamaktadır. Bu nedenle “Arama Yap” başlıklı düğmenin Click olayını temsil eden metotta aşağıdaki gibi 4 SqlParameter nesnesi hazırladım.
SqlParameter Par1 = new SqlParameter("@Par_ad", SqlDbType.Char, 20);
SqlParameter Par3 = new SqlParameter("@Par_telefon", SqlDbType.Char, 20);
SqlParameter Par4 = new SqlParameter("@Par_sehir", SqlDbType.Char, 15);
SqlParameter nesnelerini bu şekilde hazırladıktan sonra Direction özelliğinden yararlanarak yönlerini ayarlamanız ve Add() metodu ile SqlCommand nesnesinin Parameters koleksiyonuna eklemeniz gerekir. Bu amaçla aşağıda verdiğim satırları hazırladım.
Par1.Direction = ParameterDirection.Input;
Par2.Direction = ParameterDirection.Output;
Par3.Direction = ParameterDirection.Output;
Parametreleri hazırlayıp SqlCommand nesnesinin Parameters koleksiyonuna ekledikten sonra SqlCommand nesnesi ExecuteNonQuery() metodu ile işletildiği zaman kullanılacak SQL kodunun saklandığı Stored Procedure’nin adını SqlCommand nesnesinin CommandText özelliğine aktardım. Hazırladığım kodu aşağıda toplu halde verdim.
Çalışma anında formdaki ilk TextBox’a aranmak istenen firmanın adı girilip “Arama Yap” düğmesi tıklanıp yukarıda verilen kod işletilirse ilk TextBox'ın içeriği SqlCommand nesnesinin “Par1” adını vermiş olduğum Input yönlü parametresine aktarılır.
Tam bu sırada SqlCommand nesnesinin CommandText özelliğine adı aktarılmış Stored Procedure ExecuteNonQuery() ile işletilirse tabloda bulunan kaydın diğer alanları Stored Procedure’nin yönü OutPut olan parametrelerini aktarılır. Bu parametreler ile SqlCommand nesnesinin parametreleri arasında bire bir ilişki olduğu için aşağıdaki gibi bir sonuç elde edilir.
Her ne kadar tablolardan Stored Procedure ile ister 1 ister 3 bilgi çekilsin kullanım tekniği ve yazılan kod bakımından bir farklılık olmasa bile Stored Procedure ile veritabanından yönü OutPut olan parametreler sayesinde veri çekme tekniğinin mucidi yerli yazar 3 bilgi çekmenize izin vermemektedir. Yaptığım araştırmalar Stored Procedure’lerde yönü OutPut olan parametrelerin sayısının 2 olmasına bu buluşu yapan yazarın bir itirazının olup olmadığını öğrenemedim. Bana sorarsınız aynı Stored Procedure’de yönü OutPut olan 2 veya 3 parametre tanımlamak yerine 1 parametreye sahip birden fazla Stored Procedure hazırlayıp kullanın(!). Bu şekilde suç işleyip yerli yazarın hakkına tecavüz etmemiş olursunuz.
İşte bu yazının başlığında sorulan sorunun cevabı: Stored Procedure’lerin yönü OutPut olan parametreleri ile veritabanından 1 bilgiyi çekmek caiz, 3 bilgiyi çekmek caiz değildir, hatta suçtur.
Yusuf Akgül - 16.10.2009
projelerde gereksiz SP ler veritabanının özelliklede SqlServer 2005'in kasılmasına sebeb olmaz mı yani neden böle bir seçme işlemi için SP kullanalımmm anlamadım doğrusu?
ilhan aksu - 30.5.2009
Benim için çok faydalı bir makale oldu . Teşekkür ederim.