ENES TAŞ

Senior Software Developer

MS SQL'de JSON Verileriyle Çalışmak PART-3 (OPENJSON Kullanımı) 30.5.2019

Serimizin bu bölümünde elimizde JSON formatında bulunan verimizi, OPENJSON fonksiyonunu kullanarak tablomuza aktarmayı inceleyeceğiz. Bir sonraki makalede ise bir prosedür oluşturup, bu işlemi tüm tablo yapıları için dinamik bir hale getireceğiz. 

Hemen makalemizin başında da not olarak belirtelim; OPENJSON fonksiyonu ancak COMPATIBILITY_LEVEL 130 ve üzeri seviyesinde kullanılabilmektedir. Veritabanınınızın COMPATIBILITY_LEVEL seviyesini aşağıdaki komut ile güncelleyebilirsiniz. 

ALTER DATABASE [VeritabaniAdi] SET COMPATIBILITY_LEVEL=130

Önceki bölümlerde Musteri adında bir tablomuz vardı. Bu tablomuza uygun olarak JSON formatında bir verimiz olduğunu varsayalım. Bu veriyi Musteri tablomuza aktarmak istediğimiz de OPENJSON fonksiyonunu kullanmalıyız, ancak bu fonksiyon tek başına yeterli değildir. OPENJSON fonksiyonu JSON verimizi bize key, value ve type kolonları halinde dönecektir. 

Örnek; 

JSON verimizi tablo kolonlarımıza uygun şekilde dönmek istiyorsak WITH komutunu kullanmamız gerekiyor. WITH komutu yardımıyla JSON verimizi tablo şemasına uygun hale getirebiliriz. 

Örnek sorgu;

SELECT * FROM OPENJSON(@JSON)
WITH (
Adi nvarchar(50) '$.Adi', 
Telefon nvarchar(20) '$.Telefon', 
MailAdresi nvarchar(50) '$.MailAdresi', 
Adres nvarchar(2000) '$.Adres'
)    

Bu sorgumuzun sonucunda istediğimiz çıktıyı elde ediyoruz. 


Artık sadece verilerimizi tablomuza insert etmek kalıyor. Bunun içinde yazmamız gereken sorgu cümlesi aşağıdaki şekilde olmalı.

INSERT INTO Musteri
SELECT * FROM OPENJSON(@JSON)
WITH (
Adi nvarchar(50) '$.Adi', 
Telefon nvarchar(20) '$.Telefon', 
MailAdresi nvarchar(50) '$.MailAdresi', 
Adres nvarchar(2000) '$.Adres'
)        

Kayıtlarımız başarıyla eklenmiş bulunmakta. 

Peki ya senaryomuz da şöyle bir durum olsa, JSON verisinde bulunan kayıtlar tablomuzda varsa ne yapmalı? Bu durumda doğrudan insert cümlesini bu şekilde yazarsak tekrarlı kayıtlarımız olacaktır. Bunun önüne geçmek için ise OPENJSON ile aldığımız sonuç tablosundaki Adi alanıyla Musteri tablomuzun Adi alanlarını LEFT JOIN ile bağlayıp, Musteri tablosundaki Adi alanı null olanları getir şeklinde bir koşul sağlayabiliriz. Böylece Musteri tablomuzda olmayan kayıtları insert etmiş olur, tekrarlı kayıt oluşmasının önüne geçebiliriz. Bu işlemi yapmanın farklı yolları da elbet var. Öncelikle LEFT JOIN ile bu işlemi nasıl yaparız ona bakalım. JSON verimize tablomuzda olan ve bir tane de olmayan kayıt ekleyelim ve hem Musteri tablomuzdaki verileri, hemde LEFT JOIN sağlayarak JSON verimizi çekelim. 


1. YOL LEFT JOIN

Üstteki görseli incelediğimizde JSON verimizde bulunan Umut TAŞ isimli müşteri kaydı tablomuzda var, ancak Semih DİKMEN isimli müşteri kaydı tablomuzda yok. LEFT JOIN cümlemiz ve WHERE cümlemizde belirttiğimiz koşul yardımıyla Musteri tablosunda olmayan kaydın gelmesini sağladık. Bu sorgunun üzerine insert cümlemizi yazmak tekrarlı kayıt oluşturma probleminin önüne geçecektir. 

Örnek sorgumuz aşağıdaki şekilde olmalı; 

DECLARE @JSON NVARCHAR(MAX)=N'
[
   {
      "Adi":"Umut TAŞ",
      "Telefon":"555-555-55-55",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"Şafak Mah.\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   },
   {
      "Adi":"Semih DİKMEN",
      "Telefon":"555-666-66-66",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   }
]';

INSERT INTO Musteri
SELECT J.* FROM  OPENJSON(@JSON) 
WITH (
Adi nvarchar(50) '$.Adi', 
Telefon nvarchar(20) '$.Telefon', 
MailAdresi nvarchar(50) '$.MailAdresi', 
Adres nvarchar(2000) '$.Adres'
) J LEFT JOIN Musteri M ON M.Adi=J.Adi
where M.Adi is null

2. YOL WHERE NOT IN

Bir diğer yol ise hiç JOIN işlemine ihtiyaç duymadan WHERE cümlesinde NOT IN kullanmak. 

Örnek Sorgu; 

DECLARE @JSON NVARCHAR(MAX)=N'
[
   {
      "Adi":"Umut TAŞ",
      "Telefon":"555-555-55-55",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"Şafak Mah.\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   },
   {
      "Adi":"Semih DİKMEN",
      "Telefon":"555-666-66-66",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   }
]';

INSERT INTO Musteri
SELECT * FROM OPENJSON(@JSON) 
WITH (
Adi nvarchar(50) '$.Adi', 
Telefon nvarchar(20) '$.Telefon', 
MailAdresi nvarchar(50) '$.MailAdresi', 
Adres nvarchar(2000) '$.Adres'
)  WHERE Adi NOT IN (SELECT Adi FROM Musteri)    

Eğer SQL de JOIN işlemlerine hakimseniz ilk sorgu zaten sizin için gayet kolay ve anlaşılır olacaktır, JOIN işlemlerine hakim olmayanlar ise bu konu üzerine kaynakları mutlaka incelesinler. İnternette JOIN cümleleri ile ilgili oldukça kaynak olması nedeniyle bu makale de ayrıyetten JOIN konularına detaylıca girmek istemedim. 

Sorgularınızın daha sade ve anlaşılır olması açısından, özellikle daha fazla alanı bulunan tablolar için ek olarak temp tablolar kullanılabilir. Yani JSON verisi önce OPENJSON ve WITH cümleleri ile bir temp tabloya aktarılıp sonrasında Musteri tablosuyla yada ilgili tabloyla JOIN sağlanabilir veya NOT IN koşuluyla tekrarlı kayıtlar ayıklanabilir. 

Peki ya JSON verisindeki tablomuzda olmayan kayıtları insert, olanları ise update etmek istiyorsak? Bu işlem içinde insert sorgumuz iki örnekte de olduğu gibi olabilir. Update işlemi için ek olarak bir sorguya daha ihtiyacımız var sadece. Bunun için ise INNER JOIN kullanmak gerekir. 

Örnek Update sorgumuz aşağıdaki şekilde olmalı; 

DECLARE @JSON NVARCHAR(MAX)=N'
[
   {
      "Adi":"Umut TAŞ",
      "Telefon":"555-555-55-55",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"Şafak Mah.\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   },
   {
      "Adi":"Semih DİKMEN",
      "Telefon":"555-666-66-66",
      "MailAdresi":null,
      "Adres":"{\"Adres\": \"\", \"Il\": \"ANTALYA\", \"Ilce\": \"KEPEZ\"}"
   }
]';

UPDATE M SET M.Telefon=J.Telefon, M.MailAdresi=J.MailAdresi, M.Adres=J.Adres 
FROM Musteri M 
INNER JOIN OPENJSON(@JSON) 
WITH (
Adi nvarchar(50) '$.Adi', 
Telefon nvarchar(20) '$.Telefon', 
MailAdresi nvarchar(50) '$.MailAdresi', 
Adres nvarchar(2000) '$.Adres'
) J ON M.Adi=J.Adi    

Faydalı olması dileğiyle, kolay gelsin :)

Yorum Yap