Gerando XML no SQL Server – Arte do FOR XML AUTO
Como é inevitável se falar de Service Broker sem falar em XML, vou abordar nos próximos artigos a arte de gerar XML por T-SQL, que é útil para formatar dados diretamente pelo banco de dados, principalmente no caso de criar mensagens para o Service Broker ou XML para as aplicações.
Abordarei inicialmente as quatro formas básicas de geração de XML por meio da clausula FOR XML, e de acordo com a evolução dos artigos, partiremos para as técnicas de leitura e otimização.
Neste primeiro passo conheceremos o FOR XML AUTO, que é a forma mais simples para gerar XML por meio de consultas, exemplo:
SELECT TOP (5) FirstName , LastName FROM Person.Contact FOR XML AUTO
<Person.Contact FirstName="Gustavo" LastName="Achong" /> <Person.Contact FirstName="Catherine" LastName="Abel" /> <Person.Contact FirstName="Kim" LastName="Abercrombie" /> <Person.Contact FirstName="Humberto" LastName="Acevedo" /> <Person.Contact FirstName="Pilar" LastName="Ackerman" />
Com a consulta seguinte, criaremos um nó raiz para nosso XML:
SELECT TOP (5) FirstName , LastName FROM Person.Contact FOR XML AUTO , ROOT('Person') -- nó raiz
<Person> -- nó raiz <Person.Contact FirstName="Gustavo" LastName="Achong" /> <Person.Contact FirstName="Catherine" LastName="Abel" /> <Person.Contact FirstName="Kim" LastName="Abercrombie" /> <Person.Contact FirstName="Humberto" LastName="Acevedo" /> <Person.Contact FirstName="Pilar" LastName="Ackerman" /> </Person>
Separando as colunas em nós:
SELECT TOP (3) FirstName , LastName , EmailAddress FROM Person.Contact FOR XML AUTO , ELEMENTS -- Separando em nós , ROOT('Person')
<Person> <Person.Contact> <FirstName>Gustavo</FirstName> <LastName>Achong</LastName> <EmailAddress>gustavo0@adventure-works.com</EmailAddress> </Person.Contact> <Person.Contact> <FirstName>Catherine</FirstName> <LastName>Abel</LastName> <EmailAddress>catherine0@adventure-works.com</EmailAddress> </Person.Contact> <Person.Contact> <FirstName>Kim</FirstName> <LastName>Abercrombie</LastName> <EmailAddress>kim2@adventure-works.com</EmailAddress> </Person.Contact> </Person>
E como utilizar alias/apelidos para definir os nomes dos nós:
SELECT TOP (5) [Name] = FirstName + ', ' + LastName -- Alias na coluna , [Email] = EmailAddress FROM Person.Contact AS [Contact] -- Alias na tabela FOR XML AUTO , ELEMENTS , ROOT('Person')
<Person> <Contact> -- Alias da tabela <Name>Gustavo, Achong</Name> -- Alias da coluna <Email>gustavo0@adventure-works.com</Email> </Contact> <Contact> <Name>Catherine, Abel</Name> <Email>catherine0@adventure-works.com</Email> </Contact> <Contact> <Name>Kim, Abercrombie</Name> <Email>kim2@adventure-works.com</Email> </Contact> <Contact> <Name>Humberto, Acevedo</Name> <Email>humberto0@adventure-works.com</Email> </Contact> <Contact> <Name>Pilar, Ackerman</Name> <Email>pilar1@adventure-works.com</Email> </Contact> </Person>
Para ficar mais complexo o cenário, a utilização de JOINs, que segundo a ordem dos elementos que forem informados no SELECT, alteraremos a ordem da “hierarquia” dos nós:
Exemplo 1: PC como pai, PSC como filho:
SELECT TOP (5) PC.Name, -- Pai PSC.Name -- Filho FROM Production.ProductCategory AS PC INNER JOIN Production.ProductSubcategory AS PSC ON PC.ProductCategoryID = PSC.ProductCategoryID FOR XML AUTO , ROOT('P1')
<P1> <PC Name="Accessories"> -- Pai <PSC Name="Bike Racks" /> -- Filho <PSC Name="Bike Stands" /> <PSC Name="Bottles and Cages" /> <PSC Name="Cleaners" /> <PSC Name="Fenders" /> </PC> </P1>
Exemplo 2: PSC como pai, PC como filho:
SELECT TOP (5) PSC.Name, -- Pai PC.Name -- Filho FROM Production.ProductCategory AS PC INNER JOIN Production.ProductSubcategory AS PSC ON PC.ProductCategoryID = PSC.ProductCategoryID FOR XML AUTO , ROOT('P1')
<P1> <PSC Name="Bike Racks"> -- Pai <PC Name="Accessories" /> -- Filho </PSC> <PSC Name="Bike Stands"> <PC Name="Accessories" /> </PSC> <PSC Name="Bottles and Cages"> <PC Name="Accessories" /> </PSC> <PSC Name="Cleaners"> <PC Name="Accessories" /> </PSC> <PSC Name="Fenders"> <PC Name="Accessories" /> </PSC> </P1>
Obs.: Veja que a ordem do JOIN não afeta em nada, pois somente foi alterada a ordem do SELECT do primeiro exemplo para o segundo.
Exemplo 3: Vários níveis:
SELECT TOP (2) PSC.Name, -- Pai PC.Name, -- Filho PSC2.Name -- Neto FROM Production.ProductCategory AS PC INNER JOIN Production.ProductSubcategory AS PSC ON PC.ProductCategoryID = PSC.ProductCategoryID INNER JOIN Production.ProductSubcategory AS PSC2 ON PSC2.ProductSubcategoryID = PSC.ProductSubcategoryID FOR XML AUTO , ROOT('P1')
<P1> <PSC Name="Bike Racks"> -- Pai <PC Name="Accessories"> -- Filho <PSC2 Name="Bike Racks" /> -- Neto </PC> </PSC> <PSC Name="Bike Stands"> <PC Name="Accessories"> <PSC2 Name="Bike Stands" /> </PC> </PSC> </P1>