CREATE TABLE #zretezit(slovo NVARCHAR(30)) INSERT INTO #zretezit(slovo) VALUES (N'pondělí') ,(N'úterý') ,(N'středa') DECLARE @zretezeni0 NVARCHAR(MAX) = ( SELECT ','+z.slovo FROM #zretezit z FOR XML PATH('') ) PRINT @zretezeni0 /* Výsledek, všechno hraje jak má: ,pondělí,úterý,středa */ --Horší je, jak tam někdo nacpe html tagy a odřádkování INSERT INTO #zretezit(slovo) VALUES (N'<b>text</b>') ,(N'Lorem'+CHAR(13)+CHAR(10)+N'iposum') DECLARE @zretezeni1 NVARCHAR(MAX) = ( SELECT ','+z.slovo FROM #zretezit z FOR XML PATH('') ) PRINT @zretezeni1 /* Vysledkem je: ,pondělí,<b>text</b>,Lorem
 iposum */ --Pak pomáhá to zkonvertovat na NVARCHAR DECLARE @zretezeni2 NVARCHAR(MAX) = ( SELECT ( SELECT ','+z.slovo FROM #zretezit z FOR XML PATH(''), TYPE ).value('(./text())[1]','NVARCHAR(MAX)') ) PRINT @zretezeni2 /* Výsledek: ,pondělí,<b>text</b>,Lorem iposum */ --Ještě se zbavit první čárky a máme tu konstrukci jak víno: DECLARE @zretezeni3 NVARCHAR(MAX) = ( SELECT STUFF( ( SELECT ','+z.slovo FROM #zretezit z FOR XML PATH(''), TYPE ).value('(./text())[1]','NVARCHAR(MAX)') ,1 ,1 ,'' ) ) PRINT @zretezeni3 /* Krása střídá nádheru: pondělí,úterý,středa,<b>text</b>,Lorem iposum */ --Asi by bylo dobré zmínit, že od SQL 2017 funguje tohle DECLARE @zretezeni4 NVARCHAR(MAX) = ( SELECT STRING_AGG(z.slovo,',') FROM #zretezit z ) PRINT @zretezeni4
Archiv pro štítek: XML
Rychlokurz XML v T-SQL
Funkce nad xml
- query() – dotaz nad XML, výsledkem je opět XML
- value() – dotaz nad XML, vrátí hodnotu definovaného datového typu
- exists() – test, zda dotaz vrátí neprázdnou hodnotu
- modify() – modifikace XML
- nodes() – dotaz nad XML, výsledkem je tabulka s jedním sloupcem typu XML
Do XQuery dotazu můžeme dostat SQL proměnnou díky funkci sql:variable(„@nazevPromenne“) nebo hodnotu z tabulky díky funkci sql:column(„tabulka.sloupec“) .
DECLARE @xml XML SET @xml = ' <zamestnanci xmlns="nejaky-namespace"> <oddeleni typ="vyvoj"> <zamestnanec id="1"> <jmeno>Jarmil</jmeno> <prijmeni>Novák</prijmeni> <plat premie="ne" xmlns="dalsi-namespace">20000</plat> </zamestnanec> <zamestnanec id="2"> <jmeno>Vlastimil</jmeno> <prijmeni>Hujer</prijmeni> <plat premie="ano" xmlns="dalsi-namespace">40000</plat> </zamestnanec> </oddeleni> <oddeleni typ="implementace"> <zamestnanec id="3"> <jmeno>Petr</jmeno> <prijmeni>Zeman</prijmeni> <plat premie="ne" xmlns="dalsi-namespace">50000</plat> </zamestnanec> </oddeleni> </zamestnanci> '
Vypořádání se s namespace
Přečtení jedné konkrétní hodnoty, deklarace defaultního namespace
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace' ) SELECT @xml.value('(/zamestnanci/oddeleni[@typ="vyvoj"]/zamestnanec[@id="2"]/prijmeni)[1]','VARCHAR(50)') AS prijmeni /* prijmeni -------------------------------------------------- Hujer */
Přečtení jedné konkrétní hodnoty, deklarace defaultního namespace
SELECT @xml.value(' declare default element namespace "nejaky-namespace"; (/zamestnanci/oddeleni[@typ="vyvoj"]/zamestnanec[@id="2"]/prijmeni)[1]','VARCHAR(50)') AS prijmeni /* prijmeni -------------------------------------------------- Hujer */
Přečtení jedné konkrétní hodnoty, jakýkoliv namespace
SELECT @xml.value('(/*:zamestnanci/*:oddeleni[@typ="vyvoj"]/*:zamestnanec[@id="2"]/*:plat)[1]','VARCHAR(50)') AS plat /* plat -------------------------------------------------- 40000 */
Přečtení jedné konkrétní hodnoty, deklarace namespace
SELECT @xml.value(' declare namespace N="nejaky-namespace"; (/N:zamestnanci/N:oddeleni[@typ="vyvoj"]/N:zamestnanec[@id="2"]/N:prijmeni)[1]','VARCHAR(50)') AS prijmeni /* prijmeni -------------------------------------------------- Hujer */
Přečtení jedné konkrétní hodnoty, deklarace dvou namespace
SELECT @xml.value(' declare namespace N="nejaky-namespace"; declare namespace P="dalsi-namespace"; (/N:zamestnanci/N:oddeleni[@typ="vyvoj"]/N:zamestnanec[@id="2"]/P:plat)[1]','VARCHAR(50)') AS plat /* plat -------------------------------------------------- 40000 */
Čtění z XML
Vypsání všech hodnot uzlu na konkrétní úrovni, absolutní adresa
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, --používám "dalsi-namespace" x.value('P:plat[1]/@premie','VARCHAR(3)') premie --používám "dalsi-namespace" FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec') x(x) --dohledání uzlu, ke kterému se bude vztahovat funkce value /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Jarmil Novák 20000 ne Vlastimil Hujer 40000 ano Petr Zeman 50000 ne */
vypsání všech hodnot uzlu na konkrétní úrovni, relativní adresa
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('//zamestnanec') x(x)--relativní adresa /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Jarmil Novák 20000 ne Vlastimil Hujer 40000 ano Petr Zeman 50000 ne */
podmínka na hodnotu atributu
;WITH XMLNAMESPACES( 'dalsi-namespace' AS P, DEFAULT 'nejaky-namespace' ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec[@id="1"]') x(x) /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Jarmil Novák 20000 ne */
podmínka na hodnotu atributu ve větší úrovni zanoření
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec/P:plat[@premie="ne"]/..') x(x) /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Jarmil Novák 20000 ne Petr Zeman 50000 ne */
podmínka ve where
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec') x(x) WHERE x.value('P:plat[1]/@premie','VARCHAR(3)') = 'ano' /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Vlastimil Hujer 40000 ano */
čtění na základě proměnné
DECLARE @promenna INT SET @promenna = 50000 --čtění na základě proměnné, jednoduše ve where klauzuli ;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec') x(x) WHERE x.value('P:plat[1]','INT') = @promenna /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Petr Zeman 50000 ne */
čtění na základě proměnné, sql proměnná protažená do XQuery výrazu
;WITH XMLNAMESPACES( DEFAULT 'nejaky-namespace', 'dalsi-namespace' AS P ) SELECT x.value('jmeno[1]','VARCHAR(50)') AS jmeno, x.value('prijmeni[1]','VARCHAR(50)') AS prijmeni, x.value('P:plat[1]','INT') plat, x.value('P:plat[1]/@premie','VARCHAR(3)') premie FROM @xml.nodes('/zamestnanci/oddeleni/zamestnanec/P:plat1/..') x(x) /* jmeno prijmeni plat premie -------------------------------------------------- -------------------------------------------------- ----------- ------ Petr Zeman 50000 ne */
mazání
smazání uzlu
DECLARE @smaz XML SET @smaz = @xml SET @smaz.modify('delete /*:zamestnanci/*:oddeleni[@typ="vyvoj"]') --jakykoliv namespace SELECT @smaz /* <zamestnanci xmlns="nejaky-namespace"> <oddeleni typ="implementace"> <zamestnanec id="3"> <jmeno>Petr</jmeno> <prijmeni>Zeman</prijmeni> <plat xmlns="dalsi-namespace" premie="ne">50000</plat> </zamestnanec> </oddeleni> </zamestnanci> */
smazání uzlu s deklarací dafaultniho namespace
SET @smaz = @xml SET @smaz.modify(' declare default element namespace "nejaky-namespace"; delete /zamestnanci/oddeleni[@typ="vyvoj"]' ) SELECT @smaz /* <zamestnanci xmlns="nejaky-namespace"> <oddeleni typ="implementace"> <zamestnanec id="3"> <jmeno>Petr</jmeno> <prijmeni>Zeman</prijmeni> <plat xmlns="dalsi-namespace" premie="ne">50000</plat> </zamestnanec> </oddeleni> </zamestnanci> */
smazání atributu
SET @smaz = @xml SET @smaz.modify(' declare default element namespace "nejaky-namespace"; declare namespace P = "dalsi-namespace"; delete /zamestnanci/oddeleni/zamestnanec/P:plat/@premie ' ) SELECT @smaz /* <zamestnanci xmlns="nejaky-namespace"> <oddeleni typ="vyvoj"> <zamestnanec id="1"> <jmeno>Jarmil</jmeno> <prijmeni>Novák</prijmeni> <plat xmlns="dalsi-namespace">20000</plat> </zamestnanec> <zamestnanec id="2"> <jmeno>Vlastimil</jmeno> <prijmeni>Hujer</prijmeni> <plat xmlns="dalsi-namespace">40000</plat> </zamestnanec> </oddeleni> <oddeleni typ="implementace"> <zamestnanec id="3"> <jmeno>Petr</jmeno> <prijmeni>Zeman</prijmeni> <plat xmlns="dalsi-namespace">50000</plat> </zamestnanec> </oddeleni> </zamestnanci> */
modifikace
bez cyklu lze modifikovat jen jednu hodnotu
SET @smaz = @xml SET @smaz.modify(' declare default element namespace "nejaky-namespace"; declare namespace P = "dalsi-namespace"; replace value of (/zamestnanci/oddeleni/zamestnanec[@id=2]/P:plat/text())[1] with "10000" ' ) SELECT @smaz /* <zamestnanci xmlns="nejaky-namespace"> <oddeleni typ="vyvoj"> <zamestnanec id="1"> <jmeno>Jarmil</jmeno> <prijmeni>Novák</prijmeni> <plat xmlns="dalsi-namespace" premie="ne">20000</plat> </zamestnanec> <zamestnanec id="2"> <jmeno>Vlastimil</jmeno> <prijmeni>Hujer</prijmeni> <plat xmlns="dalsi-namespace" premie="ano">10000</plat> </zamestnanec> </oddeleni> <oddeleni typ="implementace"> <zamestnanec id="3"> <jmeno>Petr</jmeno> <prijmeni>Zeman</prijmeni> <plat xmlns="dalsi-namespace" premie="ne">50000</plat> </zamestnanec> </oddeleni> </zamestnanci> */
Další zdroje
http://beyondrelational.com/modules/2/blogs/28/posts/10279/xquery-labs-a-collection-of-xquery-sample-scripts.aspx
http://www.w3schools.com/xpath/default.asp
http://www.w3schools.com/xquery/default.asp