|
XML
Log kayıtlarını tutuabilmek amaçlı
bir tablo oluşturup bütün uygulamalarımızın log bilgilerini bu tabloda tutalım.Yalnız
bilgileri normal text olarak değil xml olarak tutalım ki verilerimizi ilişkisel
bir biçimde gruplandırabilelim.
Şimdi Log isminde bir tablo oluşturralım;
|
CREATE TABLE
Log
(
Id INT
IDENTITY(1,1)
PRIMARY KEY NOT
NULL,
Aciklama
XML
)
|
Şimdi ise veriyi alıp bu tabloya
ekleyen bir stored procedure yazalım;
|
CREATE PROCEDURE
LogEkle(@aciklama XML)
AS
BEGIN
INSERT INTO
Log VALUES(@aciklama)
END
|
Bu store procedure’e veri göndermke
için ise şu T-SQL kodlarını yazıyoruz;
|
DECLARE @aciklama XML
SET @aciklama =
'<log><app>Lig</app><aciklama>Takým
Eklenemedi</aciklama>
<tarih>15.12.2007</tarih></log>'
EXEC LogEkle @aciklama
|
Bu durumda kayıt tabloya eklenecektir.Eğer
XML verisi hatalı olur ise,exception fırlatılacak ve kayıt eklenmeyecektir.Girilen
XML dökümanının doğruluğunu SQL Server kontrol etmektedir.
·
XML dökümanın derinliği 128 en fazla seviye olabilir.
·
XML dökümanı en fazla 2 GB olabilir.
XML Schema
XML dökümanı için bir biçim(format)
belirlemek ve onun dışındaki verileri kabul etmemek,yani girilen XML dökümanın bazı
kriterlere uygun olmasını sağlama(zorlamak) amaçlı XML Schema’lar kullanılır.
Yukarıdaki örnekte Aciklama alanına
girilebilecek olan XML biçimini belirleyen bir schema tanımı yapalım.
Not: Schema’lar veri tabanı düzeyinde uygulanır ve saklanır.
|
CREATE XML
SCHEMA COLLECTION
LogSchema AS
'<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element
name="log">
<complexType>
<sequence>
<element name="app"
type="string"/>
<element name="aciklama"
type="string"/>
</sequence>
</complexType>
</element>
</schema>'
|
Bu tanımla birlikte, xml dökümanı
içerisinde root altında log isminde bir tag olmalı,onun içinde app ve Aciklama isminde,string
tipinde değer alan iki alt tag olmalıdır demiş oluyoruz.
Var olan bir XML Schema’yı silmek
için şu komutu kullanıyoruz;
|
DROP XML
SCHEMA COLLECTION
LogSchema
|
Şimdi isterseniz bu XML Schema tanımına
uygun bir XML değişkeni tanımlayalım;
|
DECLARE @aciklama XML(LogSchema)
SET @aciklama =
'<log><app>Lig</app><aciklama>Log mesajı</aciklama></log>'
|
Böyle bir tanımlama hata vermeycektir.Çünkü
XML değeri,Schema’ya uygun.Faka tbu tanıma uymayan bir xml değeri(xml formatına
uygun bile olsa) hatalı olacak ve exception fırlatacaktır. Örneğin yukarıdaki tanımlamayı
şu şekilde değiştirirsek hata alacağız;
|
DECLARE @aciklama XML(LogSchema)
SET @aciklama =
'<log><app>Lig</app><detay >Log mesajı</detay></log>'
|
Doğrudan SQL Server içinde Schema
tanımlamak yerine,bu tanımı bir dosyaya koyup,dosyadan yüklemek daha anlamlıdır.Yukarıdaki
schemayı,xsd uzantılı bir dosyaya kaydettikten sonra,şu şekilde yükleyebiliriz;
|
DECLARE @schema XML
SELECT @schema =
c FROM OPENROWSET(BULK
'C:\log.xsd',SINGLE_BLOB) AS TEMP(c)
CREATE XML
SCHEMA COLLECTION
LogSchema AS @schema
|
ÖRNEK: Mail bilgilerinin tutulduğu bir tablo yapalım ve bu tabloda Detay isimli
bir kolon olsun ve türü XML olsun.Bu kolona özgü bir adet xml schema tanımlayalım.Detay
kolonunda maile ait to,from,subject ve body kısımları olacaktır.
Schema oluşturalım;
|
CREATE XML
SCHEMA COLLECTION
MailSchema AS
'<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="mail">
<complexType>
<sequence>
<element name="to" type="string"/>
<element name="from" type="string"/>
<element name="subject" type="string"/>
<element name="body" type="string"/>
</sequence>
</complexType>
</element>
</schema>'
|
Tablomuzu oluşturalım;
|
CREATE TABLE
Mail
(
Id
INT IDENTITY(1,1)
NOT NULL,
Detay
XML(MailSchema) NULL,
CONSTRAINT PK_Mail PRIMARY
KEY(Id)
)
|
Tabloya kayıt ekleyelim;
INSERT INTO Mail VALUES( '<mail> <to>Ahmet</to> <from>Mehmet</from> <subject>Toplantı Var</subject> <body>Salı günü saat 15:30''da toplantımız var</body> </mail>') |
ÖRNEK: Kişiye ait Id,Ad,Soyad,Yas,Sehir,Semt ve AdresDetay bilgilerini tutmak
istiyoruz.
|
<Kisi Id="5">
<Ad>Ahmet</Ad>
<Soyad>Er</Soyad>
<Yas>30</Yas>
<Adres>
<Sehir>Ankara</Sehir>
<Semt>Öveçler</Semt>
<Detay>4.Cadde</Detay>
</Adres>
</Kisi>
|
Bu tipte bir kaydı kaydedebilecek
bir tablo yapısı ve xml schema oluşturalım;
XML Sxhema;
|
CREATE XML
SCHEMA COLLECTION
KisiSchema As
'<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="Kisi">
<complexType>
<sequence>
<element name="Ad" type="string"/>
<element name="Soyad" type="string"/>
<element
name="Yas" type="int"/>
<element
name="Adres">
<complexType>
<sequence>
<element name="Sehir" type="string" />
<element name="Semt" type="string" />
<element name="Detay" type="string"
/>
</sequence>
</complexType>
</element>
</sequence>
<attribute name="Id"
type="integer" />
</complexType>
</element>
</schema>'
|
Tablo;
|
CREATE TABLE
Kisi
(
ID
INT IDENTITY(1,1)
PRIMARY KEY NOT NULL,
Bilgi
XML(KisiSchema)
)
|
Kayıt Ekleyelim;
|
INSERT INTO
Kisi VALUES(
'<Kisi Id="5">
<Ad>Ahmet</Ad>
<Soyad>Er</Soyad>
<Yas>30</Yas>
<Adres>
<Sehir>Ankara</Sehir>
<Semt>Öveçler</Semt>
<Detay>4.Cadde</Detay>
</Adres>
</Kisi>')
|
Tablodaki Veriyi XML’e Dönüştürme
Tablolardaki verileri FOR XML ifadesi
ile XML formatına dönüştürebiliriz.
FOR XML RAW
Product tablosunu XML formatında
listeleyelim;
|
SELECT ProductID,[Name],Color,ListPrice
FROM Production.Product
FOR XML
RAW('Product'),ELEMENTS
|
Sonuç :
|
<Product>
<ProductID>1</ProductID>
<Name>Adjustable
Race</Name>
<ListPrice>0.0000</ListPrice>
</Product>
|
Kolon isimlerini değiştirmek için
AS ifadesiyle kolonları değiştirebiliriz.Element biçiminde değilde Attribute biçiminde
yapmak istersek bu durumda ELEMENTS ifadesini kaldırmamız gerekir.Şimdi sorgumuzu
şu şekilde değiştirelim;
|
SELECT ProductID AS
ID,
[Name] AS
UrunAdi,
Color AS
Renk,
ListPrice ListeFiyati
FROM Production.Product
FOR XML
RAW('Urun')
|
Sonuç:
|
<Urun
ID="877" UrunAdi="Bike Wash - Dissolver"
ListeFiyati="7.9500" />
<Urun
ID="878" UrunAdi="Fender Set - Mountain"
ListeFiyati="21.9800" />
|
·
FOR XML RAW ile içiçe tag’lar konulamaz.
·
Sadece 1 seviyede hiyerarşi oluşturabiliriz.
·
Kök tag’ı yoktur.Dolayısıyla üretilen XML dökümanı Well-Formed değildir.
FOR XML AUTO
İçiçe tag’lar içeren XML dökümanı
üretmek amaçlı kullanılır.
ÖRNEK: Her bir modeli ve o model altındaki ürünleri göstren bir XML dökümanı
oluşturalım.
|
SELECT Model.[Name],Product.ProductID,Product.[Name],Product.Color
FROM Production.Product
Product,Production.ProductModel
Model
WHERE Product.ProductModelID=Model.ProductModelID
FOR XML
AUTO,ELEMENTS
|
Sonuç:
|
<Model>
<Name>HL Road
Frame</Name>
<Product>
<ProductID>680</ProductID>
<Name>HL Road
Frame - Black, 58</Name>
<Color>Black</Color>
</Product>
<Product>
<ProductID>706</ProductID>
<Name>HL Road
Frame - Red, 58</Name>
<Color>Red</Color>
</Product>
</Model>
|
ÖRNEK: Ürünlerin kategorilerini ve modellerini XML olarak listeleyelim;
|
SELECT PC.[Name],PSC.[Name],P.ProductID,P.[Name],PM.[Name],P.Color,P.ListPrice
FROM
Production.Product P,Production.ProductSubcategory PSC,
Production.ProductCategory
PC,Production.ProductModel
PM
WHERE
P.ProductSubcategoryID=PSC.ProductSubcategoryID AND
PSC.ProductCategoryID=PC.ProductCategoryID AND
P.ProductModelID=PM.ProductModelID
ORDER BY
PC.[Name],PSC.[Name],P.ListPrice
FOR XML
AUTO,ELEMENTS
|
Sonuç:
|
<PC>
<Name>Accessories</Name>
<PSC>
<Name>Bike Racks</Name>
<P>
<ProductID>876</ProductID>
<Name>Hitch Rack
- 4-Bike</Name>
<ListPrice>120.0000</ListPrice>
<PM>
<Name>Hitch Rack - 4-Bike</Name>
</PM>
</P>
</PSC>
...
</PC>
|
FOR XML AUTO üzerine notlar;
·
Kök tag’ı yoktur,o yüzden well-formed değildir.
·
Her bir kolon aynı biçimde formatlanabilir,farklı farklı formatlanamaz.
·
Yeni bir isim verilemez.FOR XML RAW’da isim verebiliyorduk.
FOR XML PATH
SQL Server 2005 ile gelen yeni bir
özelliktir.İçiçe tag’lar oluşturmamıza izin verir ve her bir kolon için ayrı ayrı
özellik belirtebiliriz.
ÖRNEK: Modeller ve modellere ait ürünlerin bilgilerini listeleyelim;
|
SELECT Model.[Name]
'@ModelName',
Product.ProductID
'Product/Id',
Product.[Name]
'Product/Name',
Product.Color
'Product/Color',
Product.ProductNumber
'Product/Detail/ProductNumber',
Product.Size
'Product/Detail/Size',
Product.StandardCost
'Product/Detail/StandartCost'
FROM Production.Product
Product,Production.ProductModel
Model
WHERE Product.ProductModelID=Model.ProductModelID
FOR XML
PATH('Model')
|
Sonuç:
|
<Model
ModelName="HL
Road Frame">
<Product>
<Id>680</Id>
<Name>HL Road
Frame - Black, 58</Name>
<Color>Black</Color>
<Detail>
<ProductNumber>FR-R92B-58</ProductNumber>
<Size>58</Size>
<StandartCost>1059.3100</StandartCost>
</Detail>
</Product>
</Model>
|
ÖRNEK: SubCategory ve bu kategori
altındaki ürünleri şu formatta listeleyiniz;
Biçim:
|
<Kategori
Name="Road
Frames">
<Product
Id="680">
<Name>HL Road
Frame - Black, 58</Name>
<Color>Black</Color>
<Diger
ListPrice="1431.5000" />
</Product>
</Kategori>
|
T-SQL Cümlesi:
|
SELECT PSC.[Name]
'@Name',
P.ProductID
'Product/@Id',
P.[Name] 'Product/Name',
P.Color
'Product/Color',
P.ListPrice
'Product/Diger/@ListPrice'
FROM
Production.Product P,Production.ProductSubcategory PSC
WHERE P.ProductSubcategoryID=PSC.ProductSubcategoryID
FOR XML
PATH('Kategori')
|
FOR XML PATH Üzerine Notlar;
·
Kök tag’ı sağlamadığından well-formed değildir.
·
Tag’lar her bir satır için tekrarlanır.
·
Yazılımcı, kolonlar üzerinde çok fazla kontrole sahiptir
Şimdiye kadar ki bütün modellerde
kök tag’ı eklenemiyordu.Şimdi her bir modelde kullanılabilecek olan bir özelliği
kullanarak,oluşturulacak XML dökümanına kök(root) ekleyelim.
|
SELECT ProductID AS
ID,
[Name] AS
UrunAdi,
Color AS
Renk,
ListPrice ListeFiyati
FROM Production.Product
FOR XML
RAW('Urun'),
ROOT('Urunler')
|
Sonuç:
|
<Urunler>
<Urun
ID="878" UrunAdi="Fender Set - Mountain"
ListeFiyati="21.9800" />
<Urun
ID="879" UrunAdi="All-Purpose Bike Stand"
ListeFiyati="159.00" />
</Urunler>
|
NULL Değerleri Yönetmek
Gördüğümüz bu komularda,eğer bir
kolondaki değer NULL ise,SQL Server,XML dökümanına bunu eklemiyordu.Şöyle bir SQL
cümleciğini düşünelim;
|
SELECT 100 'kolon1',
200 'kolon2',
NULL
'kolon3',
400 'kolon4'
FOR XML
RAW,ELEMENTS
|
Bu sorgu sonucunda şöyle bir değer
dönecektir;
|
<row>
<kolon1>100</kolon1>
<kolon2>200</kolon2>
<kolon4>400</kolon4>
</row>
|
Görüldüğü gibi NULL olan değerleri
almamıştır.Şimdi T-SQL’imizi şu şekilde değiştirelim;
|
SELECT 100 'kolon1',
200 'kolon2',
NULL
'kolon3',
400 'kolon4'
FOR XML
RAW,ELEMENTS
XSINIL
|
Sonuç:
|
<row
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<kolon1>100</kolon1>
<kolon2>200</kolon2>
<kolon3
xsi:nil="true" />
<kolon4>400</kolon4>
</row>
|
Not:
Normalde FOR XML komutları geriye
bir string ifade döndürmektedir.Dönen değer ise aslında bir XML dökümanıdır(ROOT
kullanıyor ise).Madem ki geriye XML dönüyor,o zaman ben bu XML değerini strning
olarak değilde,XML olarak almak istiyor isem bu durumda şu kodu kullanmalıyım;
|
DECLARE @myXML XML
SET @myXML =
(SELECT 100 'kolon1',
200 'kolon2',
NULL
'kolon3',
400 'kolon4'
FOR XML
RAW,ELEMENTS
XSINIL,TYPE)
|
ÖRNEK: Her bir alt kategoriyi ve alt kategoriler altındaki ürünleri listeleyiniz.Biçimi
aşağıdaki gibi olacaktır;
|
<AllCategories>
<Category>
<Name>Bib-Shorts</Name>
<products>
<Product
ProductID="855" Name="Men's Bib-Shorts, S"
Color="Multi"/>
<Product
ProductID="856" Name="Men's Bib-Shorts, M"
Color="Multi"/>
<Product
ProductID="857" Name="Men's Bib-Shorts, L"
Color="Multi"/>
</products>
</Category>
...
</AllCategories>
|
Cevap:
|
SELECT [Name],
(SELECT ProductID,[Name],Color,ListPrice
FROM Production.Product
P
WHERE P.ProductSubcategoryID
= PSC.ProductSubcategoryID
FOR XML
RAW('Product'),TYPE)
as products
FROM Production.ProductSubcategory
PSC
FOR XML
RAW('Category'),ELEMENTS,ROOT('AllCategories')
|
|