Tenha uma iniciação rápida com o DB2 9 pureXML, Parte 3: Consulte dados XML do DB2 com SQL

O release 9 do DB2 da IBM apresenta um novo e importante suporte para o armazenamento, gerenciamento e pesquisa de dados XML, chamado pureXML. Neste artigo, aprenda como consultar dados armazenados em colunas XML usando SQL e SQL/XML. O próximo artigo da série mostrará como consultar dados XML utilizando XQuery, uma nova linguagem suportada pelo DB2.

Observação: Este artigo, originalmente escrito em 2006, foi atualizado para incluir as alterações no DB2 9.5 e 9.7.

Cynthia M. Saracco, Kiến trúc giải pháp cao cấp, EMC

Cindy Saracco photoC. M. Saracco trabalha com o Laboratório da IBM no Vale do Silício na organização de XML no DB2. Ela trabalha no gerenciamento de banco de dados, XML, desenvolvimento de aplicativo da Web e assuntos relacionados.


nível de autor Profissional do
        developerWorks

25/Mar/2010 (Primeira publicação 16/Mar/2006)

Embora a arquitetura híbrida do DB2 represente uma significativa diferença em relação aos releases anteriores, o aproveitamento dos seus novos recursos de XML não precisa ser um processo penoso. Se você já está familiarizado como a SQL, é possível empregar seu conhecimento imediatamente, trabalhando com dados XML armazenados nativamente em DB2. Veja como neste artigo.

Os recursos XML no DB2 9 incluem um novo gerenciamento de armazenamento, indexação e suporte à linguagem de consulta. Neste artigo, aprenda como consultar dados em colunas DB2 XML utilizando SQL ou SQL com extensões XML (SQL/XML). O próximo artigo da série tratará do novo suporte do DB2 para XQuery, um padrão emergente no segmento, e explorará as situações em que ele pode ser mais útil.

Você se surpreenderá ao saber que o DB2 também suporta consultas bilíngues -- isto é, consultas que combinam expressões SQL e XQuery. A linguagem (ou combinação de linguagens) usada dependerá da sua necessidade nos aplicativos, assim como de suas habilidades. A combinação de elementos de duas linguagens de consulta em uma consulta não é tão difícil quanto pode parecer. Essa combinação pode lhe proporcionar recursos poderosos para procurar e integrar dados XML e SQL tradicionais.

Banco de dados de amostra

As consultas neste artigo acessarão as tabelas de amostra criadas em "Getting off to a fast start with DB2 9, Part 2" (developerWorks, março de 2006). Para uma revisão rápida, as tabelas de amostra de "itens" e "clientes" são definidas da seguinte forma:

Listagem 1. Definições de tabela
create table items (
id 		int primary key not null, 
brandname 	varchar(30), 
itemname 	varchar(30), 
sku 		int, 
srp 		decimal(7,2), 
comments 	xml
)

create table clients(
id 		int primary key not null, 
name 		varchar(50), 
status 		varchar(10), 
contactinfo 	xml
)

Os dados XML de amostra incluídos na coluna "items.comments" estão na Listagem 2, enquanto os dados de amostra XML incluídos na coluna "clients.contactinfo" estão na Listagem 3. Os exemplos de consultas subsequentes irão se referir a elementos específicos de um ou de ambos os documentos XML.

Listagem 2. Documento XML de amostra armazenado na coluna "comments" da tabela de "items"
<Comments>
	<Comment>
		<CommentID>133</CommentID>
		<ProductID>3926</ProductID>
		<CustomerID>8877</CustomerID>
		<Message>Heels on shoes wear out too quickly.</Message>
		<ResponseRequested>No</ResponseRequested>
	</Comment>
	<Comment>
		<CommentID>514</CommentID>
		<ProductID>3926</ProductID>
		<CustomerID>3227</CustomerID>
		<Message>Where can I find a supplier in San Jose?</Message>
		<ResponseRequested>Yes</ResponseRequested>
	</Comment>
</Comments>
Listagem 3. Documento XML de amostra armazenado na coluna "contactinfo" da tabela de "clients"
<Client>
	<Address>
		<street>5401 Julio Ave.</street>
		<city>San Jose</city>
		<state>CA</state>
		<zip>95116</zip>
	</Address>
	<phone>
		<work>4084630000</work>
		<home>4081111111</home>
		<cell>4082222222</cell>
	</phone>
	<fax>4087776666</fax>
	<email>love2shop@yahoo.com</email>
</Cleint>

Ambiente de consulta

Todas as consultas neste artigo foram criadas para serem emitidas de forma interativa, o que pode ser feito através do processador de linha de comando do DB2 ou do DB2 Command Editor do DB2 Control Center. As imagens de tela e as instruções neste artigo concentram-se no segundo. (O IBM Data Studio e o IBM Optim Development Studio também vêm com um Ambiente de Trabalho do Desenvolvedor baseado em Eclipse, que pode auxiliar os programadores a formular consultas graficamente. Entretanto, este artigo não discute questões relacionadas ao desenvolvimento de aplicativos ou o Development Studio.)

Para usar o DB2 Command Editor, inicie o Control Center e selecione Tools > Command Editor. Uma janela semelhante à Figura 1 aparecerá. Digite as suas consultas na seção superior, clique na seta verde no canto superior esquerdo para executá-las e visualize a saída na seção inferior ou na guia "Query results" .

Figura 1. O DB2 Command Editor, que pode ser iniciado a partir do DB2 Control Center
Upper pane shows simple SQL query. Lower pane shows query succesful.

Consultas apenas em SQL

Mesmo que o seu conhecimento de SQL seja limitado, você poderá consultar dados XML sem muito esforço. Por exemplo, a consulta seguinte seleciona o conteúdo completo da tabela "clients", incluindo as informações XML armazenadas na coluna "contactinfo" :

Listagem 4. Instrução SELECT simples
 select * from clients

Naturalmente, você pode escrever consultas SQL mais seletivas que incorporem projeções relacionais e operações de restrição. A consulta seguinte recupera os IDs, nomes e informações de contato de todos os clientes com status "Gold". Observe que a coluna "contactinfo" contém dados XML, ao contrário das outras duas colunas:

Listagem 5. Instrução SELECT simples com projeção e restrição
select id, name, contactinfo 
from clients
where status = 'Gold'

E, como é de se esperar, é possível criar visualizações com base em tais consultas, conforme visto aqui com "goldview":

Listagem 6. Criando uma visualização que contém uma coluna XML
create view goldview as 
select id, name, contactinfo 
from clients
where status = 'Gold'

Infelizmente, há muitas coisas que não podem ser feitas apenas com SQL. As instruções apenas em SQL possibilitam que você recupere documentos XML completos (conforme acabamos de ver), mas não é possível especificar predicados de consultas baseados em XML, nem recuperar documentos XML parciais ou valores de elementos específicos de um documento XML. Em outras palavras, não é possível projetar, restringir, juntar, agregar ou ordenar por fragmentos de documentos XML utilizando apenas SQL. Por exemplo, não é possível recuperar apenas os endereços de e-mail de seus clientes "Gold" ou os nomes de clientes que moram no código postal "95116". Para expressar esses tipos de consultas, é necessário usar a SQL com extensões XML (SQL/XML), XQuery ou uma combinação de ambos.

A próxima seção explora diversos recursos fundamentais da SQL/XML. E em um artigo subsequente, aprenda a escrever em XQuery, assim como combinar XQuery com SQL.


Consultas SQL/XML

Como o nome indica, a SQL/XML foi concebida para construir uma ponte entre os mundos da SQL e do XML. Ela foi desenvolvida como parte da iniciativa do padrão SQL e agora inclui especificações para integrar expressões XQuery ou XPath dentro das instruções SQL. A XPath é uma linguagem para a navegação em documentos XML para encontrar elementos ou atributos. A XQuery inclui suporte para a XPath.

É importante observar que as expressões XQuery (e XPath) diferenciam maiúsculas e minúsculas. Por exemplo, a XQuery que fizer referência ao elemento XML "zip" (código postal) não se aplicará aos elementos XML denominados "ZIP" ou "Zip". Às vezes, é difícil para os programadores de SQL se lembrarem da diferenciação de maiúsculas e minúsculas, já que a sintaxe de consultas SQL permite o uso de "zip", "ZIP" e "Zip" para se referir ao mesmo nome de coluna.

O DB2 9 apresenta mais de 15 funções SQL/XML que permitem que você procure dados específicos em documentos XML, converta dados relacionais em XML, converta dados XML em dados relacionais e realize outras tarefas úteis. Este artigo não abrange toda a extensão da SQL/XML. Entretanto, ele analisa diversos desafios comuns de consultas, assim como a maneira como as principais funções SQL/XML podem enfrentar esses desafios.

"Restringindo" resultados com base em valores de elementos XML

Frequentemente, os programadores de SQL escrevem consultas que restringem as linhas retornadas do DBMS com base em alguma condição. Por exemplo, a consulta SQL na Listagem 5 restringe as linhas recuperadas da tabela "clients" para incluir apenas os clientes com status "Gold". Nesse caso, o status do cliente é capturado em uma coluna SQL VARCHAR. Mas e se você quiser restringir a busca com base em alguma condição que se aplica aos dados de uma coluna XML? A função XMLExists da SQL/XML proporciona um meio de fazer isso.

XMLExists permite que você navegue a um elemento no seu documento XML e teste uma condição específica. Quando especificado como parte da cláusula WHERE, XMLExists restringe os resultados retornados somente àquelas linhas que contém um documento XML com o valor específico do elemento XML (em outras palavras, onde o valor especificado é avaliado como "true").

Examinemos um problema de consulta levantado anteriormente. Imagine que você precisa localizar os nomes de todos os clientes que moram em um determinado código postal. Como você deve se lembrar, a tabela "clients" armazena os endereços dos clientes (incluindo código postal) em uma coluna XML. (Consulte a Listagem 3.) Usando XMLExists, é possível procurar o código postal desejado na coluna XML e restringir o conjunto de resultados de forma apropriada. A consulta SQL/XML seguinte retorna os nomes dos clientes que moram no código postal 95116:

Listagem 7. Restringindo resultados com base em um valor de elemento XML
select name from clients
where xmlexists('$c/Client/Address[zip="95116"]'
passing clients.contactinfo as "c")

A primeira linha é uma cláusula SQL que especifica que você só quer recuperar informações na coluna "name" da tabela "clients". A cláusula WHERE invoca a função XMLExists, especificando uma expressão XPath que avisa o DB2 para navegar ao elemento "zip" e verificar se há o valor 95116. A cláusula "$c/Client/Address" indica o caminho na hierarquia do documento XML onde o DB2 pode localizar o elemento "zip". Utilizando dados acessíveis a partir do nó "$c" (que explicaremos em breve), o DB2 navegará através do elemento "Client" para o seu subelemento "Address" para inspecionar o código postal (valores "zip"). A linha final resolve o valor de "$c": é a coluna "contactinfo" da tabela "clients". Dessa forma, o DB2 inspeciona os dados XML contidos na coluna "contactinfo", navega a partir do elemento-raiz "Client" para "Address" e então para "zip", e determina se o cliente mora no código postal procurado. Se a resposta for sim, a função XMLExists avalia como "true", e o DB2 retorna o nome do cliente relacionado àquela linha.

Um erro comum envolve a formulação do predicado de consulta XMLExists, conforme demonstrado na Listagem 8.

Listagem 8. Sintaxe incorreta para restringir resultados baseados em um valor de elemento XML
select name from clients
where xmlexists('$c/Client/Address/zip="95116" '
passing clients.contactinfo as "c")

Embora executada com sucesso, esta consulta não restringe os resultados aos clientes que moram no código postal 95116. (Isso se deve à semântica especificada no padrão; não é exclusiva do DB2.) Para restringir os resultados aos clientes que moram no código postal 95116, é necessário utilizar a sintaxe mostrada anteriormente na Listagem 7.

Talvez você esteja curioso para saber como incluir uma consulta que restringe dados XML em um aplicativo. Embora este artigo não trate de temas de desenvolvimento de aplicativos em detalhes, ele inclui um exemplo simples em Java que utiliza um marcador de parâmetro dentro de uma instrução SQL/XML para restringir as saídas às informações sobre clientes que moram em um determinado código postal.

"Projetando" valores de elementos XML

Vamos considerar agora uma situação um pouco diferente, na qual queremos projetar valores XML em nosso conjunto de resultados retornado. Isto é, queremos recuperar um ou mais valores de elementos dos nossos documentos XML. Há muitas maneiras de se fazer isso. Primeiro, vamos usar a função XMLQuery para recuperar o valor de um elemento e então usar a função XMLTable para recuperar valores de vários elementos e mapeá-los em colunas de um conjunto de resultados SQL.

Vamos pensar em como solucionar um problema proposto anteriormente: como criar um relatório relacionando os endereços de e-mail dos clientes "Gold". A consulta seguinte na Listagem 9 invoca a função XMLQuery para realizar esta tarefa:

Listagem 9. Recuperando informações de e-mail para clientes qualificados
select xmlquery('$c/Client/email' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'

A primeira linha especifica que você quer retornar valores para o subelemento "email" do elemento-raiz "Client". A segunda e a terceira linha indicam onde o DB2 pode encontrar essa informação -- na coluna "contactinfo" da tabela "clients". A quarta linha qualifica a sua consulta para indicar que você está interessado apenas nos endereços de e-mail de clientes "Gold". Essa consulta retornará um conjunto de elementos e valores XML. Por exemplo, se você tiver 500 clientes "Gold", cada um com um endereço de e-mail, a sua saída seria uma coluna com 500 linhas, conforme mostrado na Listagem 10:

Listagem 10. Saída de amostra para consulta anterior
1
--------------------------------------------

<email>user5976@anyprovider.com</email>
. . . 
<email>someID@yahoo.com</email>

Se houver vários endereços de e-mail para cada cliente "Gold", é possível instruir o DB2 para retornar somente os endereços primários (ou seja, o primeiro endereço de e-mail encontrado no documento "contactinfo" do cliente). É possível modificar a expressão XPath na primeira linha da sua consulta para fazer isso:

Listagem 11. Recuperando o primeiro endereço de e-mail de cada cliente qualificado
select xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'

Finalmente, se faltarem endereços de e-mail de alguns clientes "Gold", é possível escrever uma consulta para excluir os resultados nulos do conjunto de resultados. Para fazer isso, modifique a consulta anterior acrescentando outro predicado à cláusula WHERE para testar as informações de e-mail ausentes. Você já está familiarizado com a função SQL/XML que lhe permite fazer isso -- XMLExists. A Listagem 12 mostra como é possível reescrever a consulta anterior para filtrar as linhas de clientes "Gold" cujas informações de contato (armazenadas como XML) não incluem o endereço de e-mail:

Listagem 12. Recuperando o primeiro endereço de e-mail de cada cliente qualificado para os quais temos no mínimo um endereço de e-mail
select xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients 
where status = 'Gold'
and xmlexists('$c/Client/email' passing contactinfo as "c")

Agora, vamos considerar uma situação um pouco diferente, na qual é necessário recuperar vários valores de elementos XML. XMLTable gera saídas tabulares a partir de dados armazenados em colunas XML e é muito útil por proporcionar aos programadores uma visualização "relacional" dos dados XML. Assim como XMLExists e XMLQuery, a função XMLTable faz com que o DB2 navegue através da hierarquia do documento XML para localizar os dados de interesse. Entretanto, XMLTable também inclui cláusulas para mapear os dados XML desejados em colunas de conjuntos de resultados de tipos de dados SQL.

Considere a seguinte consulta (Listagem 13), que projeta colunas de dados relacionais e de dados XML armazenados na tabela "items". (Consulte a Listagem 2 para examinar a tabela "items".) Os IDs de comentários, IDs de clientes e as mensagens são armazenados em documentos XML na coluna "comments". Os nomes dos itens são armazenados em uma coluna SQL VARCHAR.

Listagem 13. Recuperando vários elementos XML e convertendo cada um em um tipo de dado SQL tradicional
select t.Comment#, i.itemname, t.CustomerID, Message from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns Comment# integer path 'CommentID',
	CustomerID integer path 'CustomerID',
	Message varchar(100) path 'Message') as t

A primeira linha especifica as colunas a serem incluídas no conjunto de resultados. As colunas entre aspas e prefixadas com a variável "t" são baseadas em valores de elementos XML, como indicam as linhas subsequentes da consulta. A segunda linha invoca a função XMLTable para especificar a coluna XML do DB2 contendo os dados de destino ("i.comments") e o caminho dentro dos documentos XML da coluna, onde os elementos de interesse estão localizados (dentro do subelemento "Comment" do elemento-raiz "Comments"). A cláusula "colunas", que abarca as linhas de 3 a 5, identifica os elementos XML específicos que serão mapeados para as colunas de saída no conjunto de resultados SQL, especificadas na linha 1. Parte desse mapeamento envolve a especificação dos tipos de dados para os quais os valores de elementos XML serão convertidos. Neste exemplo, todos os dados XML são convertidos em tipos de dados SQL tradicionais.

A Figura 2 mostra exemplos de resultados da execução desta consulta. Como você pode ver, a saída é um simples conjunto de resultados SQL. Observe que os nomes das colunas foram transformados em letras maiúsculas -- uma ocorrência normal com SQL.

Figura 2. Saída de amostra de uma consulta utilizando a função XMLTable
Query results screen showing four columns of data

Se desejado, é possível usar XMLTable para criar conjuntos de resultados que também incluem colunas XML. Por exemplo, a instrução seguinte produz um conjunto de resultados similar ao anterior, exceto pelo fato dos dados de "Message" estarem contidos em uma coluna XML em vez de uma coluna SQL VARCHAR.

Listagem 14. Recuperando vários elementos XML e convertendo-os em tipos tradicionais de dados SQL ou XML
select t.Comment#, i.itemname, t.CustomerID, Message from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns Comment# integer path 'CommentID',
	CustomerID integer path 'CustomerID',
	Message XML by ref path 'Message') as t

Criando visualizações relacionais de dados XML

Como você pode imaginar, as funções de SQL/XML podem ser usadas para definir visualizações. Isso é especialmente útil se você quiser apresentar aos seus programadores de aplicativos SQL um modelo relacional dos seus dados XML nativos.

Criar uma visualização relacional com base em dados de uma coluna XML não é muito mais complexo do que projetar valores de elementos XML. Basta escrever uma instrução SQL/XML SELECT que invoque a função XMLTable, e usar isso como base para sua definição de visualização. O exemplo seguinte na Listagem 15 cria uma visualização baseada em informações de colunas XML e não-XML da tabela "items". (É similar à consulta na Listagem 13.)

Listagem 15. Criando uma visualização com base na saída de XMLTable
create view commentview(itemID, itemname, commentID, message, mustrespond) as 
select i.id, i.itemname, t.CommentID, t.Message, t.ResponseRequested from items i, 
xmltable('$c/Comments/Comment' passing i.comments as "c"
columns CommentID integer path 'CommentID',
	Message varchar(100) path 'Message',
	ResponseRequested varchar(100) path 'ResponseRequested') as t;

Embora seja fácil criar visualizações relacionais com base em dados de colunas XML, deve-se considerar o seu uso com cautela se você não estiver usando a V9.7. Antes da V9.7, o DB2 não utilizava índices de colunas XML quando as consultas eram emitidas contra tais visualizações. Dessa forma, se você indexasse o elemento ResponseRequested e emitisse uma consulta SQL que restringisse os resultados da coluna "mustrespond" a um certo valor, o DB2 leria todos os documentos XML e procuraria o valor de "ResponseRequested" apropriado. A menos que existisse apenas uma pequena quantidade de dados, isso diminuiria o desempenho do tempo de execução. Assim, até que seja feita a atualização para a V9.7, tenha cuidado quando o DB2 utilizar índices XML em predicados SQL.

Unindo dados relacionais e XML

A esta altura, você deve estar se perguntando como unir dados XML com dados que não sejam XML (dados relacionais com base em tipos tradicionais de SQL, por exemplo). O DB2 possibilita que você faça isso com uma única instrução SQL/XML. Embora existam maneiras diferentes de formular tais junções, dependendo do seu esquema de banco de dados e dos requisitos de carga de trabalho, abordaremos um exemplo aqui. E você pode ficar surpreso ao saber que já possui conhecimento suficiente sobre SQL/XML para realizar a tarefa.

Lembre-se de que a coluna XML na tabela "items" contém um elemento "CustomerID". Isso pode servir como uma chave de junção para a coluna "id" baseada em número inteiro na tabela "clients". Assim, se você quiser um relatório dos nomes e status dos clientes que comentaram sobre um ou mais produtos, será necessário unir valores de elementos XML de uma tabela com valores SQL de números inteiros de outra. E uma maneira de realizar isso é usar a função XMLExists, conforme demonstrado na Listagem 16:

Listagem 16. Unindo dados XML e não-XML
select clients.name, clients.status from items, clients
where xmlexists('$c/Comments/Comment[CustomerID=$p]'
passing items.comments as "c", clients.id as "p")

A primeira linha identifica as colunas SQL a serem incluídas no conjunto de resultados da consulta e as tabelas de origem referidas na consulta. A segunda linha inclui a cláusula de junção. Aqui, XMLExists determina se o valor "CustomerID" em uma fonte de destino é igual a um valor derivado de outra fonte de destino. A terceira linha especifica estas fontes: a primeira é a coluna XML "comments" na tabela "items", e a segunda é a coluna de número inteiro "id" na tabela "clients". Desse modo, se um cliente tiver comentado sobre qualquer item, e as informações sobre esse cliente estiverem disponíveis na tabela "clients", a expressão XMLExists avaliará como "true" e o nome do cliente, assim como suas informações de status, serão incluídos no relatório.

Usando expressões "FLWOR" em SQL/XML

Apesar de termos abordado apenas algumas funções, a SQL/XML oferece muitos recursos poderosos para consultar dados XML e integrá-los com dados relacionais. De fato, você já viu alguns exemplos de como fazer isso, mas trataremos de mais alguns aqui.

Tanto a função XMLExists quanto a função XMLQuery permitem que você incorpore XQuery em SQL. Nossos exemplos anteriores mostram como utilizar essas funções com simples expressões XPath para navegar até uma parte do documento XML de interesse. Agora, vamos considerar um exemplo simples, no qual você inclui XQuery em suas consultas SQL.

XQueries podem conter algumas ou todas as cláusulas seguintes: "for", "let", "where", "order by" e "return". Conjuntamente, elas formam expressões FLWOR (pronunciadas flauer). Os programadores de SQL podem considerar conveniente incorporar XQueries em suas listas SELECT para extrair (ou projetar) fragmentos de documentos XML em seus conjuntos de resultados. E embora essa não seja a única maneira como a função XMLQuery possa ser usada, esse é o cenário que este artigo aborda. (Um artigo posterior desta série discute a XQuery de forma mais profunda).

Vamos supor que você queira recuperar os nomes e os endereços de e-mail primários de seus clientes "Gold". Sob alguns aspectos, essa tarefa é semelhante a outra que realizamos anteriormente (consulte a Listagem 11), na qual exploramos como projetar valores de elementos XML. Aqui, transmite-se XQuery (com cláusulas "for" e "return") como entrada para a função XMLQuery:

Listagem 17. Recuperando dados XML através do uso de cláusulas "for" e "return" de XQuery
select name, xmlquery('for $e in $c/Client/email[1] return $e' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

A primeira linha especifica que os nomes de clientes e as saídas da função XMLQuery serão incluídos no conjunto de resultados. A segunda linha indica que o primeiro subelemento "email" do elemento "Client" deve ser retornado. A terceira linha identifica a origem de nossos dados XML -- a coluna "contactinfo". A linha 4 nos informa que esta coluna está na tabela "clients". Finalmente, a quinta linha indica que somente os clientes "Gold" nos interessam.

Devido ao fato desse exemplo ter sido tão simples, a mesma consulta poderia ser escrita aqui. Ao invés disso, é possível escrever a mesma consulta de maneira mais compacta, como foi feito anteriormente:

Listagem 18. Reescrevendo a consulta anterior de maneira mais compacta
select name, xmlquery('$c/Client/email[1]' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

Contudo, a cláusula return de XQuery possibilita que você transforme a saída XML conforme necessário. Por exemplo, é possível extrair valores de elementos de e-mail e publicá-los como HTML. A consulta seguinte produzirá um conjunto de resultados no qual o primeiro endereço de e-mail de cada cliente "Gold" é retornado como um parágrafo HTML.

Listagem 19. Recuperando e transformando XML em HTML
select xmlquery('for $e in $c/Client/email[1]/text() 
return <p>{$e}</p>' 
passing contactinfo as "c") 
from clients
where status = 'Gold'

A primeira linha indica que você está interessado na representação em texto do primeiro endereço de e-mail dos clientes qualificados. A segunda linha especifica que essa informação deve ser circundada por marcações HTML de parágrafo antes do retorno. Especificamente, as chaves ( { } ) instruem o DB2 a avaliar a expressão delimitada (no caso, "$e") em vez de tratá-la como uma cadeia de caractere literal. Se as chaves forem omitidas, o DB2 retornará um conjunto de resultados contendo "<p>$e</p>" para cada registro de cliente qualificado.

Publicando dados relacionais como XML

Até o momento, nós nos concentramos nas formas de consultar, extrair ou transformar os dados contidos em uma coluna XML do DB2. E, como você pôde notar, esses recursos estão todos disponíveis através da SQL/XML.

A SQL/XML também oferece outros recursos úteis. Entre eles, está a capacidade de converter ou publicar dados relacionais como XML. Este artigo trata apenas de três funções SQL/XML nesse sentido: XMLElement, XMLAgg e XMLForest.

XMLElement permite que você converta dados armazenados nas colunas SQL tradicionais em fragmentos de XML. Ou seja, é possível construir elementos XML (com ou sem atributos XML) a partir de seus dados SQL de base. O exemplo seguinte aninha o uso da função XMLElement para criar uma série de elementos de item, cada um contendo subelementos para o ID, o nome da marca e os valores de stock keeping unit ("sku"), obtidos na tabela "items":

Listagem 20. Usando XMLElement para publicar dados relacionais como XML
select xmlelement (name "item", 
	xmlelement (name "id", id), 
	xmlelement (name "brand", brandname), 
	xmlelement (name "sku", sku) ) from items 
where srp < 100

A execução desta consulta produzirá um resultante semelhante a:

Listagem 21. Exemplo de saída da consulta anterior
<item>
  <id>4272</id>
  <brand>Classy</brand>
  <sku>981140</sku>
</item>
. . . 
<item>
  <id>1193</id>
  <brand>Natural</brand>
  <sku>557813</sku>
</item>

É possível combinar XMLElement com outras funções de publicação SQL/XML para construir e agrupar valores XML, aninhando-os em hierarquias conforme desejado. O exemplo na Listagem 22 usa XMLElement para criar elementos de customerList cujo conteúdo é agrupado de acordo com os valores na coluna de "status". Pare cada registro de "customerList", a função XMLAgg retorna uma sequência de elementos de cliente, cada uma incluindo subelementos baseados nas colunas "name" e "status". Além disso, os valores de elemento de clientes são ordenados de acordo com o nome dos clientes.

Listagem 22. Agregando e agrupando dados
select xmlelement(name "customerList",
xmlagg (xmlelement (name "customer", 
xmlforest (name as "fullName", status as "status") )
order by name ) )
from clients 
group by status

Vamos supor que a tabela "clients" contenha três valores distintos de "status": "Gold", "Silver" e "Standard". A execução da consulta anterior fará com que o DB2 retorne três elementos de customerList, cada um podendo conter vários subelementos de cliente que contém ainda informações de nome e de status. Assim, a saída será parecida com:

Listagem 23. Exemplo de saída da consulta anterior
<customerList>
  <customer>
    <fullName>Chris Bontempo</fullname>
    <status>Gold</status>
  </customer>
  <customer>
    <fullName>Ella Kimpton</fullName> 
    <status>Gold</status>
  </customer>
. . . 
</customerList>
<customerList>
  <customer>
    <fullName>Lisa Hansen</fullName>
    <status>Silver</status>
  </customer>
. . .
</customerList>
<customerList>
  <customer>
    <fullName>Rita Gomez</fullName>
    <status>Standard</status>
  </customer>
. . .
</customerList>

Operações de atualização e exclusão

Embora o foco deste artigo seja a procura e a recuperação de dados armazenados em colunas XML usando SQL, vale a pena dedicar alguns momentos a outras duas tarefas comuns: atualizar e excluir dados em colunas XML.

O DB2 9 permite que os usuários atualizem e excluam dados XML usando instruções SQL e SQL/XML. De fato, devido ao fato do rascunho inicial do padrão XQuery não abordar essas questões, os usuários do DB2 tiveram que recorrer à SQL para essas tarefas. Entretanto, a W3C estava trabalhando em um XQuery Update Facility, que foi implementado no DB2 9.5. A adição do XQuery Update Facility (inicialmente chamado TRANSFORM) simplificou muito a atualização de atributos e elementos em um documento XML, e estabeleceu um padrão para fazer isso. O XQuery Update Facility está agora na condição de Candidato a Recomendação.

Atualizando dados XML.

Ao passo que o DB2 9 possibilitava a atualização de uma coluna XML com uma instrução SQL UPDATE ou através do uso de um procedimento armazenado fornecido pelo sistema (DB2XMLFUNCTIONS.XMLUPDATE), com o DB2 9.5 é possível usar o novo XQuery Update Facility. Isso possibilita atualizar, inserir, excluir e criar um novo elemento ou atributo dentro de um documento XML existente, sem a necessidade de recriar o documento inteiro. O Update Facility também pode ser usado para modificar vários nós na mesma transação.

Por exemplo, se você quiser emitir uma instrução UPDATE para alterar o endereço de e-mail nas informações de contato de um cliente específico, basta fornecer o novo endereço de e-mail.

Considere o seguinte exemplo:

Listagem 24: Exemplo de instrução UPDATE
update clients
set contactinfo = xmlquery( '
          copy $new := $CONTACTINFO
          modify do replace value of $new/client/email with "newemail@someplace.com"
          return  $new' ) 
where id = 3227;

"copy $new", "modify do replace of $new" e "return $new" são cláusulas requeridas do XQuery Update Facility. Aprenda mais sobre a sintaxe exata e as opções na seção de Recursos abaixo. Incluímos tanto o site da especificação XQuery quanto um artigo do developerWorks que fornece mais detalhes sobre o XQuery Update Facility.

Excluindo dados XML

Excluir linhas que contêm colunas XML é um processo fácil. A instrução SQL DELETE permite que você identifique (ou restrinja) as linhas que você deseja excluir através de uma cláusula WHERE. Essa cláusula pode incluir predicados simples para identificar valores de colunas não-XML ou funções SQL/XML para identificar valores de elementos XML contidos em colunas XML.

Por exemplo, aqui mostramos como é possível excluir todas as informações do cliente com ID 3227:

Listagem 25. Excluindo dados de um cliente específico
delete from clients 
where id = 3227

Você se lembra de como restringir instruções SQL SELECT para retornar apenas as linhas dos clientes que moram no código postal 95116? Caso se lembre, é possível aplicar esse conhecimento facilmente para excluir as linhas que rastreiam esses clientes. Pode-se fazer isso usando XMLExists:

Listagem 26. Excluir dados de clientes em um código postal específico
delete from clients
where xmlexists('$c/Client/Address[zip="95116"]'
passing clients.contactinfo as "c");

Indexando

Finalmente, vale a pena observar que é possível criar índices XML especializados para agilizar o acesso aos dados armazenados em colunas XML. Como este é um artigo introdutório e há poucos dados de amostra, o tópico não será abordado aqui. Porém, em ambientes de produção, a definição de índices apropriados pode ser crucial para alcançar o máximo desempenho. A seção de Recursos deste artigo pode ajudá-lo a aprender mais sobre as novas tecnologias de indexação do DB2.


Resumo

Este artigo abordou uma grande diversidade de tópicos, destacando vários aspectos fundamentais da SQL/XML, assim como o modo como ela pode ser usada para consultar dados em colunas XML. É definitivamente possível fazer mais coisas com as funções SQL e SQL/XML do que foi tratado aqui. Este artigo inclui um exemplo simples em Java que ilustra como é possível usar marcadores de parâmetros com a SQL/XML para consultar dados em colunas XML. Discutiremos em mais detalhes questões relacionadas ao desenvolvimento de aplicativos em um artigo futuro. Contudo, o próximo artigo irá explorar alguns aspectos interessantes da XQuery, uma nova linguagem de consulta suportada pelo DB2 9.

Agradecimentos

Agradeço a George Lapis, Matthias Nicola, Sriram Padmanabhan, Gary Robinson, Hardeep Singh e Bert Van der Linden pela sua ajuda neste artigo.

Recursos

Aprender

Obter produtos e tecnologias

  • Elabore seu próximo projeto de desenvolvimento com o software de teste IBM, disponível para download diretamente no developerWorks.
  • Agora é possível usar o DB2 gratuitamente. Faça o download do DB2 Express-C, uma versão sem custos do DB2 Express Edition para a comunidade, que oferece os mesmos recursos principais de dados do DB2 Express Edition e fornece uma base sólida para construir e implementar aplicativos.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Information Management
ArticleID=483301
ArticleTitle=Tenha uma iniciação rápida com o DB2 9 pureXML, Parte 3: Consulte dados XML do DB2 com SQL
publish-date=03252010