MSSQL Merge Komutu Kullanımı

  • 4.1.2016
  • tayyipyetis
  • MSSQL

mssql merge using

Merhaba arkadaşlar, bu makalemde henüz yeni öğrendiğim ve çok faydalı bulduğum bir mssql komutundan bahsedeceğim. öyle ki projelerimizde zaman zaman iş mantığında açıklar ortaya çıkabiliyor ve bunların çözümü için kaçamak yollar arayışına girebiliyoruz bu geçici çözümler kısa vadede işe yarasa da uzun vadede çok cansıkıcı olabiliyor ve gereksiz kaynak ve zaman tüketimine sebep olabiliyor bu bahsettiğim olay sadece veritabanı için değil tüm web teknolojileri için geçerli. Bundan ötürü yapmak istediğimiz şeyin uzun da olsa, daha fazla kod yazmayı da gerektirse en mantıklı yolunu seçmek mecburiyetindeyiz ki ileride başımız ağrımasın. Bu makalede ise mssql veritabanında benim de çok yakın zaman kadar yaptığım hatanın daha doğrusu yukarıda bahsettiğim kaçamak yolların hem tutarlı hem de pratik yolunu göstereceğim.

Bir veritabanı uygulaması geliştirirken çoğu zaman bir çok tablo birbiriyle doğrudan ilişkilidir ve herhangi birinde meydana gelecek bir hata diğer tablolarında yanlış veri kaydetmesine veya uygulamanızın hata vermesine sebep olur örneğin; sisteminize bir üye kaydedeceksiniz ve bunun için bir uyeler tablonuz var ve bu üyelerin iletişim bilgilerini kaydetmek için ise uye_iletisim tablonuz var doğal olarak ikisi arasında birebir bir ilişki kuruldu ve her bir kayıt için ikisinde de en az ve tek bir kayıt bulunmak zorunda ve karmaşık bir sisteminiz olduğunu varsayarsak her üyenin kayıt aşamasında iletişim bilgilerinin alınmayacağı durumlar da olabilir mesela email kampanyanızdan gelenleri doğrudan kullanıcı adı şifre ile kaydettiriyorsunuz site arayüzünden gelenlerden detaylı(iletişim bilgisi dahil) bilgi alıyorsunuz vs. bu durumda üyenin müşteri panelinden bilgilerini güncelleme durumunda iletişim bilgisini ilk defa girme olasılığı da olabilir. işte tam da bu durum için Merge komutunu kullanmak mantıklı olacaktır. Her zaman dediğim gibi bir problemin birden fazla çözümü olabilir örneğin bunu kod tarafında da çözebilirsiniz ya da Trigger kullanarak da halledebilirsiniz mühim olan en mantıklı yolu kullanmaktır. Aşağıda Merge komutunun kullanım şablonu yer almaktadır.

MERGE INTO musteriler m USING (sql cümlesi ON karşılaştırma şartı)
WHEN MATCHED THEN UPDATE cümlesi
WHEN NOT MATCHED THEN INSERT cümlesi

burada müşteriler tablosu işlem yapacağımız ana tablomuz using komutu ile başka bir tablodan ya da yine müşteriler tablosundan veri çekerek karşılaştırma yapacağımız verileri elde ediyoruz ON komutu ile bir nevi WHERE gibi karşılaştırma şartını belirtiyoruz. when matched then eğer karşılaşma var ise şunu yap anlamına geliyor ki genel de update kullanılıyor ama delete de kullanılabilir aşağıda örnek kullanımı gösterilecektir. when not matched then ile de eğer karşılaşma yok ise şunu yap denilir. ve bu da genelde insert olur.

MERGE INTO musteriler m USING (SELECT '92', 'test_verisi') AS m2 (ID, mAdi) ON (m.ID = m2.ID)
WHEN MATCHED THEN UPDATE SET m.mAdi = m2.mAdi
WHEN NOT MATCHED THEN INSERT (mAdi) VALUES(m2.mAdi);

Diğer bir kullanım örneği

MERGE INTO musteriler m USING 
(SELECT ID, mAdi FROM musteriler) as kaynak (ID, mAdi) ON (m.ID = kaynak.ID)
WHEN MATCHED THEN UPDATE SET m.mAdi = kaynak.mAdi
WHEN NOT MATCHED THEN INSERT (mAdi) VALUES(kaynak.mAdi)
OUTPUT $action, inserted.*, deleted.*;

Silme işlemi yapmak için

MERGE INTO musteriler m USING (SELECT '92', 'test_verisi') AS m2 (ID, mAdi) ON (m.ID = m2.ID)
WHEN MATCHED THEN DELETE
WHEN NOT MATCHED THEN INSERT (mAdi) VALUES(m2.mAdi);

Karşılaşmanın olup olmadığını uygulama tarafında öğrenmek istiyorsanız.

MERGE INTO musteriler m USING (SELECT '91', 'test_verisi') AS m2 (ID, mAdi) ON (m.ID = m2.ID)
WHEN MATCHED THEN UPDATE SET m.mAdi = m2.mAdi
WHEN NOT MATCHED THEN INSERT (mAdi) VALUES(m2.mAdi)
OUTPUT $action, inserted.*, deleted.*;

Şimdi ufak bir örnek senaryo üzerinden gidelim. üyelerinizin sahip olduğu yetenekleri tuttuğunuz bir tablonuz olsun örneğin; c#, mongodb, aspnet mvc gibi ve bunları belirli bir listeden seçebilsin ve seçimi kaldırabilsin tablosu yapısında ise üyenin id değeri ve yeteneğin id değeri olsun dolayısı ile bir üye için birden fazla kayıt olabilir. şimdi üye 5 tane de yetenek seçebilir 10 tane de başka bir zaman 3 taneye de indirebilir. bu güncellemeleri veritabanında yapmanın pek çok yöntemi vardır fakat her dediğim gibi "her zaman en pratik ve en mantıklı" yöntemi bulmak gerekir. benim kendim için bulduğum ki zaten tam da bu konu için geliştirilen yöntem MERGE komutu kullanarak tek bir sql cümlesi içerisinde tüm işlemleri yapabilmek yani öyle bir cümle yazmalıyız ki "sana gönderdiğim kayıt tabloda var ise birşey yapma (yada güncelle) yok ise ekle ve veri içerisinde olmayan bir kayıt sende var ise onu sil" demeliyiz. işte aşağıdaki örnek tam da bu işlemleri sağlıyor

MERGE INTO uyeyetenek AS TARGET USING (VALUES (12345, 'csharp'), (12345, 'mongodb'), (12345, 'xml')) AS n (uyeid, yetenekid) ON (TARGET.uyeid = n.uid and TARGET.yetenekid = n.yetenekid) 
WHEN NOT MATCHED BY SOURCE AND (TARGET.uyeid=12345) THEN DELETE 
WHEN NOT MATCHED AND n.yetenekid !=0 THEN INSERT (uyeid, yetenekid) VALUES(n.uyeid, n.yetenekid);

Eğer aynı kayıtlar var ise kontrol edilmeyen başka sütunları güncellemek için aşağıdaki şartı da ekleyebilirsiniz

WHEN MATCHED THEN UPDATE SET tarih = n.tarih;

Umarım faydalı olmuştur.

Mustafa Tayyip YETİŞ
Yazılım Geliştirme Uzmanı

Yorum Gönder

Diğer Makaleler

Etiketler