Makale Özeti

XML artık her firma tarafından geçerliliği kabul edilen ve kullanılan bir veri biçimi haline geldi ve verilerin sıralanması, saklanması ve iletimi için yoğun olarak kullanılıyor. Microsoft SQL Server 2000 XML kullanımını SQLXML ile sağlamaktaydı ve SQLXML size verilerinizi XML olarak kaydetme ve XML formatındaki verileri veritabanı sunucunuza aktarabilme imkanı sağlıyordu. SQL Serverın bir sonraki sürümü , SQL Server 2005 (kod adı: Yukon - Beta 1) bu desteği XMLi bir temel bir veri türü olarak kabul ederek ve XML dokumanları için yeni bir sorgulama dili sunarak sağlamakta..

Makale

XML artık her firma tarafından geçerliliği kabul edilen ve kullanılan bir veri biçimi haline geldi ve verilerin sıralanması, saklanması ve iletimi için yoğun olarak kullanılıyor. Microsoft SQL Server 2000 XML kullanımını SQLXML ile sağlamaktaydı ve SQLXML size verilerinizi XML olarak kaydetme ve XML formatındaki verileri veritabanı sunucunuza aktarabilme imkanı sağlıyordu. SQL Serverın bir sonraki sürümü , SQL Server 2005 (kod adı: Yukon - Beta 1) bu desteği XMLi bir temel bir veri türü olarak kabul ederek ve XML dokumanları için yeni bir sorgulama dili sunarak sağlamakta.

Bu dokuman dört ana bölümden oluşmakta. XML veri türü bölümü yeni veri türünü, XML Schema Management bölümü XML verileri ile kullanmak üzere XML Şemalarının nasıl register edilebileceğini, yönetilebileceğini, XQuery bölümü XMLe yönelik geliştirilen sorgulama dili olan XQueryi ele alıyor ve son bölümümüz olan ForXml ve OpenXml İfadeleri bölümünde ise XML formatındaki verilerin okunması ve yazılması konularını ele alınıyor olacağız.

SQL Server "Yukon" Beta 1 AdventureWorks adlı bir örnek veritabanı içermektedir. Bu dokumanda yer alan kod örneklerinin büyük bölümü bu veritabanına yönelik yazılmıştır. Bu dokumandaki sql ifadelerinin denemek isterseniz AdventureWorks veritabanını kurmanız gerekecektir. Aynı zamanda dikkat edilmesi gereken bir diğer nokta, AdventureWorks CaSe SeNsItIvE bir veritabanıdır, dolayısıyla tablolara, sütun ve satırlara ve diğer veritabanı nesnelerine referans verirken bunu aklınızda bulundurmanız gerekecektir.

Büyük olasılıkla sütunlarda görüntülenen karakter sayısını değiştirmek isteyeceksiniz. Aksi halde XML sonuçları sıklıkla kısaltılacaktır. Bunu yapmak için SQL Server "WorkBench" aracını çalıştırın, Tools -> Options yolunu izleyin. Query Editor Options seçeneğini genişletin ve Max Characters per Column değerini 8192 olarak değiştirin.


XML Veri Türü
XML, SQL Server tarafından saklanabilen diğer veri türlerine oranla çok daha komplex bir türdür. Örnek olarak string tabanlı veri türleri olan char ve varchar XMLin çok sayıdaki güçlü özelliğinin tam olarak kullanılması için yeterli değildir. Örneğin eğer XML string olarak saklanırsa dokuman içeriğinde sorgulama yapamaz sadece dokumanın tümünü seçebilir veya ekleyebilirsiniz. XML veri türü aracılığıyla SQL Server "Yukon" size bir XML dokumanının bölümleri arasında sorgulama, ekleme, düzenleme işlemleri yapabilme, dokumanın xml şeması ile uyumluluğunu doğrulama imkanı sağlıyor. SQL Server "Yukon" aynı zamanda SQL Server 2000de mümkün olmayan bir işlemi; ilişkisel verilerin, yapılandırılmamış (unstructured) veya yarı-yapılandırılmış (semi-structured) XML dokumanları ile entegrasyonunu sağlıyor.

SQL Server "Yukon"da XML daha kolay işlenebilmesi amacıyla binary large objects (blobs) şeklinde saklanmaktadır. Bu nedenle çoğu durumda XML veri türü nvarchar(max) veri türü ile benzer özelliklere sahiptir. Bu yaklaşımın dezavantajı sorguların XML BLOBın her seferinde önce parse edilmesi ve sorgunun daha sonradan execute edilmesinden kaynaklanan (kabul edilebilir) yavaşlıktır. Ancak XML veri türündeki alan üzerinde bir index oluşturulması bu sorunu büyük ölçüde ortadan kaldırmaktadır.  Bu konuyu dokumanın ilerleyen bölümlerinde "Performans" başlığında ele alıyor olacağız.

XML veri türünü herhangi bir diğer SQL türü gibi kullanabilirsiniz. Bu tablolarda XML sütunlar oluşturmayı, değişkenler, parametreler veya function-return türleri deklare etmeyi kapsamaktadır.  XML veri türü aynı zamanda t-sql dilindeki CAST ve CONVERT fonksiyonları ile de çalışmaktadır. Örneğin aşağıdaki kod örneği, yeni bir tablo oluşturmakta, veri türü xml olarak tanımlanmış alana bir default value assign etmektedir.

CREATE TABLE OrderDetail (
OrderID int primary key,
CustomerID int,
Products XML default CAST(<product><id/></product> as XML) NOT NULL)

SQL Server "Yukon" veri türü xml olarak tanımlanmış alanlara kaydedilen string türündeki değerler üzerinde cast işlemini otomatik olarak gerçekleştirdiğinden bunu sizin ayrıca belirtmeniz gerekmemektedir.

Bu bölümde ele alacağımız son konu ise xml olarak tanımlanmış bir alanın bir xml şeması ile birlikte kullanılması, xml veri türü metotları ve xml veri türünün kısıtlamaları..

Typed vs. UnTyped XML
Opsiyonel olarak XML türündeki bir değişkeni veya alanı bir XML şemasıyla ilişkilendirebilirsiniz. Bu size xml şemalarının sağladığı tüm avantajlardan faydalanma imkanı verir. XML verisinin indexlenmesinin bir diğer avantajı ise azalan depolama boyutu ve performans artışıdır.

Sütun ve Değişkenler
Typed xml değişkenler veya sütunlar oluşturabilmeniz için ilk olarak şemanın SQL Servera kayıt edilmesi gerekmektedir. (Bu konu "Şemaların Yönetimi" bölümünde detaylı olarak ele alınacaktır) Şema bir defa kayıt edildikten sonra şemayı xml değişken deklerasyonunda parantez içinde hedef alan adını belirterek ilişkilendirebilirsiniz.

CREATE TABLE OrderDetail (
OrderID int primary key,
CustomerID int,
Products XML(http://schemas.adventure-works.com/products))

Şema kayıt edildikten sonra, bir sütu veya değişken onu refere ettiği sürece silinemez. Aynı zamanda typed xml üzerinde cast işlemi gerçekleştirmek verinin doğrulanması işleminin gerçekleştirilmesine neden olur ve veri geçersiz ise bir hata mesajı oluşturulur. Aynı zamanda bir typed xml örneğinin untyped xml veri türüne cast edilmesi sonucunda veri örneği untype edilecek bu nedenle bu veri üzerinde değişiklik yapılamayacak ve veri şemaya uymayacaktır.

Retyping ve Untyping İşlemleri
Bir sütunu farklı bir şemayı kullanacak şekilde değiştirme veya sütunu hiçbir şemayı kullanmayacak şekilde güncelleme ihtiyacı duyabilirsiniz. Örneğin bir xml alanı ile ilişkilendirilmiş bir XML şemasını veritabanından silmek isterseniz ilk olarak kurulmuş ilişkiyi kaldırmanız gerekecektir.

Alter Column ifadesi Create Column ifadesine oldukça benzer bir söz dizimiyle bize bu imkanı vermektedir.

ALTER TABLE Store
ALTER COLUMN Demographics XML (http://schemas.adventureworks.
com/Individual/Survey)

Bir sütun type edildiğinde XML verisi yeniden doğrulanır. Aslında bu tutarlılığı sağlamaktadır.. SQL Serverın diğer veri türlerinde işlem yaparken bir sütunun veri türü üzerinde değişiklik yaptığımız zaman veriyi doğruladığını hatırlayalım.. XML veri türünün, bir XML şeması ile ilişkilendirildiği zaman dahi bir farklılığı yoktur.

Tümüyle yeni bir şemanın sütun ile ilişkilendirilmesini kapsadığından "Retyping" aslında yanlış bir adlandırılma olarakda kabul edilebilir. Gerçekte,sıklıkla yapılmak istenen sadece mevcut bir sütunun şema ile kurulmuş bağının kaldırılmasıdır. Bunu yukarıdakine oldukça benzer bir ifade ile kolayca gerçekleştirebiliriz. Bu sefer yapmamız gereken tek şey, bir şema URIi göndermemektir. Demographics sütunu üzerinde bu işlemi gerçekleştiriyoruz.

ALTER TABLE Store
ALTER COLUMN Demographics XML

Eğer hangi XML sütunlarının bir şema ile ilişkilendirildiğinden (typed) emin değilseniz, çeşitli katalog görünümleri size yardımcı olabilir. Örneğin aşağıdaki sorgu sonuç olarak tüm typed sütunları dönecektir.

SELECT c.xml_namespace_id, o.Name As TableName, c.name As
TypedColumnName, n.name As Uri
FROM sys.all_columns c
JOIN sys.all_objects o ON c.object_id=o.object_id
JOIN sys.xml_namespaces n ON c.xml_namespace_id = n.xml_namespace_id
WHERE c.xml_namespace_id IS NOT NULL

XML Veri Türü ile İlgili Metodlar
XML veri türü ile ilgili pek çok metot mevcuttur. Metotların üçü; query(), value() ve exist() XQuery ifadeleridir. Dördüncü metot modify() ise XQuery extensions kullanarak veri üzerinde değişiklik yapma imkanı sağlamaktadır. (Bu konuyu XQuery bölümünde detaylı olarak ele alıyor olacağız)

query()
Query() metodu XML veri türündeki bir alan üzerinde sorgulama yapmak için kullanılır ve sonuç olarak yine XML formatında sonuç döndürür.  Sözdizimi şu şekildedir;

SELECT ColumnName::query(XQuery Expression) AS NameOfResult

AdventureWorks veritabanındaki "individual person" tablosunun bir typed xml sütunda demografik bilgileri sakladığını varsayalım. Aşağıda, bu alanın ilk satırındaki veri yer almaktadır:

<IndividualSurvey xmlns="http://schemas.adventureworks.com/Individual/Survey">
     <DateOfFirstPurchase>Jul 12 1994 12:00AM</DateOfFirstPurchase>
     <BirthDate>Aug 18 1978 12:00AM</BirthDate>
     <MaritalStatus>S</MaritalStatus>
     <YearlyIncome>25001-50000</YearlyIncome>
     <Gender>M</Gender>
     <NoOfChildren>0</NoOfChildren>
     <NoOfChildrenAtHome>0</NoOfChildrenAtHome>
     <Education>Partial Hi</Education>
     <Occupation>Manual</Occupation>
     <HomeOwnerFlag>0</HomeOwnerFlag>
     <NoOfCarsOwned>2</NoOfCarsOwned>
     <Hobby>Golf</Hobby>
     <Hobby>Watch TV</Hobby>
</IndividualSurvey>

Bu veriyi dikkate alarak, XML verisinin YearlyIncome elemanının değerini almak istediğimizi varsayarsak kullanacağımız XQuery sorgu ifadesi şu şekilde olacaktır:

SELECT Demographics::query(default namespace="http://schemas.adventure-works.com/Individual/Survey" /IndividualSurvey/YearlyIncome)
FROM Individual

Bu sorgunun sonucunda /IndividualSurvey/YearlyIncome XPath ifadesi ile eşleşen elemana sahip satırlardan elde edilen bilgileri içeren bir sonuç kümesi döner..

<YearlyIncome xmlns="http://schemas.adventureworks.com/Individual/Survey">25001-50000</YearlyIncome>
<YearlyIncome xmlns="http://schemas.adventureworks.com/Individual/Survey">25001-50000</YearlyIncome>
<YearlyIncome xmlns="http://schemas.adventureworks.com/Individual/Survey">75001-100000</YearlyIncome>
<YearlyIncome xmlns="http://schemas.adventureworks.com/Individual/Survey">0-25000</YearlyIncome>
<YearlyIncome xmlns="http://schemas.adventureworks.com/Individual/Survey">25001-50000</YearlyIncome>

Elbette Query ifadesi ile dönen sonuçları filtrelemek için bir Transact-SQL WHERE ifadesi kullanabilirsiniz. WHERE ifadesi, SELECT ifadesinde yer alan XQUERY ifadesi çalıştırıldıktan sonra işlenecektir. Bu bize sonuçlar içinda daha detaylı filtreleme yapabilme imkanı sağlamaktadır. XQUERY ifadeleri, FLWR ifadeleri bölümünde göreceğiniz üzere, aynı zamanda WHERE ifadeleride içerebilmektedirler.

value()
value() ifadesi, bir elemanın etiketlerini değilde (veya attributeın) sadece içeriğini elde etmek için kullanılır. Bu ifadede, dönecek veri türünü belirtmeniz gerekmektedir..

SELECT TOP 5 Demographics::value(default namespace ="http://schemas.adventure-works.com/Individual/Survey" /IndividualSurvey/YearlyIncome, varchar(20))
FROM Individual

Bu sorgu aşağıdaki sonucu dönecektir.

25001-50000
25001-50000
75001-100000
0-25000
25001-50000

String tabanlı veri türlerine dönüştürme yapacağınız zaman, query metodu içinde data() veya string() XQUERY fonksiyonlarını da kullanabilirsiniz.

value metodu SELECT ifadesi içinde de kullanılabilir. Bu metodu xml tabanlı bir sütunun refere edildiği hemen her yerde kullanabilirsiniz. Örneğin 5 ila 7 çocuk sahibi ev sahiplerini listelemek için WHERE ifadesi içinde BETWEEN ve value() ifadelerini bir arada kullanabilirsiniz.

SELECT COUNT(Demographics::query(default namespace ="http://schemas.adventure-works.com/Individual/Survey"
/IndividualSurvey[HomeOwnerFlag="1"])) As NumHomeOwner
FROM Individual
WHERE Demographics::value(default namespace="http://schemas.adventure-works.com/Individual/Survey"
/IndividualSurvey/NoOfChildren,int) BETWEEN 5 AND 7

Bu sorgunun SELECT ifadesinde bir XPATH qualifier içerdiğine dikkat edelim: (/IndividualSurvey[HomeOwnerFlag="1"]).

exist()
exist() metodu belirtilen kriterlerle eşleşen bir nodeun olup olmadığını denetleme imkanı vermektedir. XQUERY ifadesi bir veya daha çok sayıda eşleşen node ile dönerse sonuç olarak 1, aksi halde sonuç olarak 0 dönecektir.

SELECT contactid, AdditionalContactInfo::value(default namespace="http://schemas.adventure-works.com/Additional/ContactInfo"
namespace act="http://schemas.adventure-works.com/AdditionalContactTypes"/AdditionalContactInfo/act:eMail[position()=1]/act:eMailAddress,varchar(50)) as result
FROM Contact

Bu ifadenin sonucunda bize yarısı NULL olan 10 satır dönecektir. XML veri türüne ait metotlarda NULL değeri, hücredeki XML verisi XQUERY ifadesi ile eşleşmediği durumlarda döner. Bu nedenle NULL kayıtları filtrelemek için WHERE AdditionalContactInfo IS NOT NULL ifadesi yeterli olmayacaktır. Bu ifade yerine exist() metodunu kullanmamız gerekecektir:

WHERE AdditionalContactInfo::exist(default namespace="http://schemas.adventure-works.com/Additional/ContactInfo"
namespace act="http://schemas.adventure-works.com/AdditionalContactTypes"
/AdditionalContactInfo/act:eMail) = 1

Sorguya bu WHERE ifadesini eklemek sonuç kümesindeki NULL kayıtları filtreleyecektir.

modify()
XML verisini veritabanından okuyabildiğimiz gibi, XML verisi üzerinde değişiklik te yapabiliriz. Bazı durumlarda bu işlem daha yüksek performans sağlayabilmektedir.

modify() metodu XML Data Modification Language constructlarını kullanmaktadır. Şu anda XQUERY spesifikasyonu XML dokumanlarının XQUERY ile değiştirilmesi yönünde herhangi bir madde içermemektedir. Bu nedenle XML DML Microsoft tarafından sağlanan bir extension durumundadır ve XQUERYnin ileriki sürümerine entegre edilmek üzere incelenmesi amacıyla W3Cye iletilmiştir.

XML DML ile XML dokumanları üzerinde aşağıdaki örnekteki gibi değişiklikler gerçekleştirebilirsiniz:

UPDATE Individual
SET Demographics::modify(default namespace="http://schemas.adventure-works.com/Individual/Survey"
insert <Comments>Bikes are cool.</Comments> into /IndividualSurvey)
WHERE IndividualID = 1

Bu örnekte insert üç XML DML metodundan biridir. Diğer iki metot ise delete ve update metotlarıdır.

Kısıtlamalar
2 GB veri depolama limitine ek olarak XML veri türünün kısıtlamaları aşağıdaki gibidir:
   - Primary Key, Foreign Key, Unique, Collate ve Rule Constraintlerini desteklemez.
   - String dışındaki veri türlerinden XMLe dönüştürmeyi desteklemez. Herhangi bir string alanı alter table ifadesini kullanarak xml veri türüne dönüştürebilirsiniz.
   - GROUP BY ifadesini desteklemez.
   - ISNULL ve COALESCE fonksiyonları dışındaki fonksiyonlarda parametre olarak kullanılamaz.
   - Stringe dönüştürülebilmesine ve string türünden XMLe dönüşüme izin vermesine rağmen bir string formatı değildir.
   - Ek olarak XML veri türündeki sütunlar bir clustered veya non-clustered indexin bir bölümü olamaz. Ancak XML veri türündeki bir alanın içeriğini indexlemek için CREATE XML INDEX ifadesini kullanabilirsiniz. (Bu konu "Performans" başlığında ele alınacaktır.)


Yazı dizimizin ilk bölümünde SQL Server 2005 ile tanışacağımız yeni veri türü olan XML veri türünü ele aldık. Bir sonraki bölümde ise XML Şema Yönetimi konusunu ele alıyor olacağız.

Kadir Sümerkent
kadirs@yazgelistir.com