SQL Server kullanan web uygulamaları
geliştiriyorken, herhangi bir sorguyu uygulamaya ait olan tüm tablolar
veya tüm veritabanları üzerinde çalıştırmayı istemek çok seyrek
karşılaşılan bir durum değil. Buna verilebilecek en yaygın iki örnek
muhtemelen bir veritabanı içerisindeki tüm tabloları silmek ve tüm
tabloların collation değerini değiştirmektir. Benzer şeyleri bir SQL
Server instance üzerindeki tüm veritabanları için yapmak da istenebilir.
Bir
çok kişinin böyle durumlarda çözüm olarak gördüğü şey söz konusu
sorguyu her tablo/veritabanı için bir kez çalıştırmaktır. Ancak bu
yöntemin aslında bir çözüm olmadığı tablo/veritabanı sayısı arttıkça
gittikçe kullanılamaz bir hal al almasından belli olmaktadır.
Konu hakkında biraz daha bilgi sahibi olan kişilerin aklına ise büyük
ihtimalle cursor kullanmak ya da verdikleri sorguyu söz konusu olan her
tablo/veritabanı için bir kez çalıştıracak olan bir stored procedure
yazmak gelecektir. Her iki çözüm de yukarıdaki paragrafta bahsettiğim
çözüme göre çok daha mantıklı olmakla birlikte, basit işler için
karmaşık ve gereksizdir. Öyle olmasının sebebi ise SQL Server'daki
master veritabanı içerisinde bu tür işlemlerin kolaylıkla yapılmasını
sağlayacak stored procedure'lerin zaten tanımlanmış olmasıdır. Bu
yazımda, bahsetmiş olduğum işlemleri tek komutla yapmanızı sağlayan,
çok işe yarar bulduğum sp_Msforeachtable ve sp_MSforeachdb
prosedürlerinden bahsedeceğim.
sp_MSforeachtable
Bu prosedür, adından da anlaşılabileceği üzere parametre olarak verilen bir sorguyu veritabanındaki tüm tablolar üzerinde çalıştırmak için kullanılır. Prosedürün alabildiği parametreler hakkında bilgi alabilmek için yine master veritabanı içerisinde tanımlı olan sp_helptext adlı prosedürü aşağıdaki şekilde kullanabilirsiniz.
EXEC sp_helptext sp_MSForEachTable
Ancak yukarıdaki prosedürü kullanmanız şart değil çünkü ben burada gerekli bilgileri zaten vereceğim. Prosedürü çağrırken kullanmanız gereken sentaks aşağıdaki şekilde.
EXEC @RETURN_VALUE=sp_MSforeachtable
@command1, @replacechar, @command2, @command3, @whereand, @precommand, @postcommand
Burada görünen parametrelerden biraz bahsetmem gerekirse:
@RETURN_VALUE: Prosedürün çalıştıktan sonra geri döndüreceği değer.
@command1: Prosedürün çalıştıracağı ilk sorgu.
@replacechar: Sorgu katarında o anda işlenmekte olan tablo adı ile değiştirilecek olan karakter. Varsayılan karakter soru işaretidir (?).
@command2 ve @command3: İlk sorgu çalıştırıldıktan sonra sırayla çalıştırılacak olan diğer iki sorgu. Eğer her tablo için birden fazla sorgu çalıştırmak istiyorsanız bu iki parametreyi kullanabilirsiniz.
@whereand: - Sorguya koşul eklemek için kullanabileceğiniz parametre.
@precommand: Herhangi bir tablo üzerinde işlem yapılmadan önce çalıştırılacak olan sorgu.
@postcommand: Sorgular tüm veritabanları üzerinde çalıştırıldıktan sonra en son olarak çalıştırılacak olan sorgu.
Parametrelerin fazlalığı gözünüzü korkutmasın, çünkü büyük ihtimalle çoğunu kullanma ihtiyacı duymayacaksınız. Aşağıdaki örneklerin prosedürü kullanmayı öğrenmeniz için yeterli olacağını düşünüyorum.
EXEC sp_MSforeachtable 'DROP TABLE ?'
EXEC sp_MSforeachtable 'DELETE FROM ?'
EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
Yukarıdaki sorgulardan ilki veritabanındaki tüm dosyaları silmek için, ikincisi veritabanındaki tüm tabloların içini boşaltmak için, üçüncüsü de veritabanındaki tüm tablolardaki constraint'leri disable etmek için kullanılabilir.
Biraz daha karmaşık bir örnek için, veritabanındaki tüm tablolardaki satır sayısını öğrenip başka bir tabloya yazmak istediğimizi varsayalım. Bunun için önce satır sayılarını yazacağımız bir tablo yaratalım.
CREATE TABLE deneme (tablo_adi varchar(50), satir_sayisi int)
Aşağıdaki sorguyu kullanarak amacımıza ulaşabiliriz.
EXEC sp_MSforeachtable 'INSERT INTO deneme SELECT ''?'',COUNT(*) FROM ?'
Şimdi de sorguyu sadece adları a veya b harfleri ile başlayan veritabanlarını seçecek şekilde değiştirelim.
EXEC sp_MSforeachtable
@command1 = 'INSERT INTO deneme SELECT ''?'', COUNT(*) FROM ?',
@whereand = 'and ad LIKE ''a%'' or ad LIKE ''b%'''
Gördüğünüz üzere bu sefer parametre adlarını da gösterdim. Bunu yapmam şart değildi, sadece daha anlaşılır olsun diye öyle yazdım. Daha önce yazmış olduğum sorgularda sadece tek parametre (@command1 parametresini) kullandığım için parametre adını yazma gereği duymamıştım. Yazıp yazmamak kişinin tercihine kalmış bir şey.
sp_MSforeachdb
Bu prosedürün sentaksı ve kullanımı sp_MSforeachtable prosedürü ile tamamen aynı. Aradaki tek fark önceki prosedür parametre olarak verilen işlemleri veritabanındaki her tablo için yaparken, bu prosedürün aynı işlemleri söz konusu SQL Server Instance içerisindeki tüm veritabanları için yapması.
Örneğin aşağıdaki sorguyu kullanarak hangi veritabanının ne kadar yer tuttuğunu öğrenebiliriz. Bu örnekte prosedüre parametre olarak verdiğiniz sorguda başka bir prosedür çağırabileceğinizi de görüyorsunuz.
EXEC sp_MSforeachdb 'EXEC sp_spaceused'
Bu prosedür ile ilgili daha fazla bir şey söylememe gerek olduğunu sanmıyorum. Daha önce de söylediğim gibi kullanımı sp_MSforeachdb ile çok benzer, hatta aynı.