Comience a usar DB2 9 pureXML ya mismo, parte 3: Consulte datos XML de DB2 con SQL

La versión DB2 9 de IBM ofrece una nueva y significativa compatibilidad con las funciones de almacenamiento, gestión y consulta de datos XML (pureXML). En este artículo, aprenderá a consultar datos almacenados en columnas XML usando SQL y SQL/XML. En el siguiente artículo de esta serie, aprenderá a consultar datos XML usando XQuery, un nuevo lenguaje compatible con DB2.

Nota: Este artículo, originariamente escrito en 2006, fue actualizado de manera que refleje los cambios introducidos en DB2 9.5 y 9.7.

Cynthia M. Saracco, Senior Software Engineer, EMC

Cindy Saracco photoC. M. Saracco trabaja en el Silicon Valley Laboratory de IBM, en la organización DB2 XML. Se ocupa de la gestión de bases de datos, XML, el desarrollo de aplicaciones Web y otros temas relacionados.


Nivel de autor profesional en developerWorks

04-05-2010 (Primera publicación 04-05-2010)

Si bien la arquitectura híbrida de DB2 se aparta considerablemente de las versiones anteriores, utilizar las nuevas capacidades XML no tiene por qué ser un proceso difícil. Si usted ya está familiarizado con SQL, ponga en práctica sus capacidades de inmediato trabajando con datos XML almacenados de forma nativa en DB2. En este artículo aprenderá cómo hacerlo.

Las características XML de DB2 9 presentan una nueva compatibilidad con las funciones de gestión de almacenamiento, indización y lenguajes de consulta. En este artículo, aprenderá a consultar datos de las columnas XML de DB2 usando SQL o SQL con extensiones XML (SQL/XML). El siguiente artículo de esta serie tratará la nueva compatibilidad de DB2 con XQuery, un nuevo estándar de la industria, y analizará su utilidad.

DB2 también es compatible con consultas bilingües, es decir, consultas que combinan expresiones tanto de SQL como de XQuery. El lenguaje (o combinación de lenguajes) que se debe usar dependerá de las necesidades de su aplicación, así como de sus aptitudes. Combinar elementos de dos lenguajes de consulta en una única consulta no es tan difícil como puede parecer. Más aún, esta combinación ofrece capacidades eficaces de búsqueda y de integración de datos SQL tradicionales y XML.

Base de datos de muestra

Las consultas de este artículo accederán a las tablas de muestras creadas en "Comience a usar DB2 9 pureXML de inmediato, parte 2" (developerWorks, marzo de 2006). A modo de repaso, se definen a continuación las tablas de muestra "items" y "clients":

Listado 1. Definición de tablas
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 )

Los datos XML de muestra incluidos en la columna "items.comments" se muestran en el listado 2, y los datos XML de muestra incluidos en la columna "clients.contactinfo", en el listado 3. Los siguientes ejemplos de consulta harán referencia a elementos específicos de uno o ambos documentos XML.

Listado 2. Documento XML de muestra almacenado en la columna "comments" de la tabla "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>
Listado 3. Documento XML de muestra almacenado en la columna "contactinfo" de la tabla "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>

Entorno de consultas

Todas las consultas de este artículo han sido diseñadas para una emisión interactiva, que se puede llevar a cabo mediante el procesador de líneas de comandos de DB2 o el editor DB2 Command Editor de DB2 Control Center. Las instrucciones e imágenes de pantalla del presente artículo corresponden a este último. (IBM Data Studio e IBM Optim Development Studio también incluyen una mesa de trabajo basada en Eclipse que ayuda a los programadores a construir consultas gráficamente; sin embargo, este artículo no trata de cuestiones de desarrollo de aplicaciones ni de Development Studio).

Para usar DB2 Command Editor, inicie Control Center y seleccione Tools (Herramientas)> Command Editor (Editor de comandos). Se abrirá una ventana similar a la de la figura 1. Escriba las consultas en el panel superior y haga clic en la flecha verde que aparece en el ángulo superior izquierdo para ejecutarlas. Los resultados se pueden visualizar en el panel inferior o en la pestaña "Query results" ("Resultados de consulta").

Figura 1. DB2 Command Editor, que se puede iniciar desde DB2 Control Center
DB2 Command Editor, que se puede iniciar desde DB2 Control Center

Consultas SQL

Aun cuando sus conocimientos de SQL sean limitados, podrá consultar datos XML con poco esfuerzo. Por ejemplo, la siguiente consulta selecciona el contenido completo de la tabla "clients", incluyendo la información XML almacenada en la columna "contactinfo":

Listado 4. Instrucción SELECT simple
select * from clients

Por supuesto que es posible escribir consultas SQL más selectivas que incorporen operaciones relacionales de proyección y restricción. La siguiente consulta recupera los ID, nombres e información de contacto de todos los clientes con estado "Gold". Observe que "contactinfo" contiene datos XML, mientras que las otras dos columnas no:

Listado 5. Instrucción SELECT simple con proyección y restricción
select id, name,
                contactinfo from clients where status = 'Gold'

Como es de esperar, se pueden crear vistas basadas en estas consultas; ver el ejemplo de "goldview":

Listado 6. Creación de una vista que contenga una columna XML
create view goldview
                as select id, name, contactinfo from clients where status = 'Gold'

Desafortunadamente, hay muchas cosas que no se pueden hacer solo con SQL. Las instrucciones SQL simples permiten recuperar documentos XML completos (como acabamos de ver), pero no es posible especificar predicados de consultas basadas en XML ni recuperar documentos XML parciales o valores de elementos específicos de un documento XML. En otras palabras, no se puede proyectar, restringir, combinar, agregar ni ordenar por fragmentos de documentos XML usando únicamente SQL. Por ejemplo, no es posible recuperar solamente las direcciones de correo electrónico de los clientes "Gold" o los nombres de los clientes que viven en el código postal "95116". Para expresar este tipo de consultas, es necesario usar SQL con extensiones XML (SQL/XML), XQuery o una combinación de ambos.

En la siguiente sección se analizarán diversas características fundamentales de SQL/XML; en un futuro artículo aprenderá a escribir XQuery y a combinar XQuery y SQL.


Consultas SQL/XML

Como lo indica su nombre, SQL/XML sirve como puente entre los mundos SQL y XML. Evolucionó como parte del estándar SQL y ahora incluye especificaciones para incrustar expresiones XQuery o XPath dentro de instrucciones SQL. XPath es un lenguaje que permite navegar por un documento XML para buscar diferentes elementos y atributos. XQuery es compatible con XPath.

Es importante destacar que las expresiones XQuery (y XPath) distinguen mayúsculas de minúsculas. Por ejemplo, una expresión XQuery que hacer referencia al elemento XML "zip" no se aplicará a los elementos XML denominados "ZIP" o "Zip". A veces, esta distinción entre mayúsculas y minúsculas es pasada por alto por los programadores SQL, ya que la sintaxis de consulta SQL les permite usar "zip", "ZIP" y "Zip" para referirse al mismo nombre de columna.

DB2 9 tiene más de 15 funciones SQL/XML que permiten buscar datos específicos dentro de los documentos XML, convertir datos relacionales en XML, convertir datos XML en relacionales y realizar otras tareas útiles. Este artículo no abarca toda la amplitud de SQL/XML. Sin embargo, analiza varios desafíos habituales que presentan las consultas y la manera en que las principales funciones SQL/XML abordan estos desafíos.

"Restricción" de resultados en función de valores de elementos XML

Los programadores SQL suelen escribir consultas que restringen las filas devueltas por el DBMS en función de cierta condición. Por ejemplo, la consulta SQL del listado 5 restringe las filas devueltas de la tabla "clients" de manera de incluir solamente a aquellos clientes con estado "Gold". En este caso, el estado del cliente es capturado en una columna VARCHAR de SQL. Pero ¿es posible restringir la búsqueda en función de cierta condición aplicable a los datos de una columna XML? La función XMLExists de SQL/XML ofrece un medio para hacerlo.

XMLExists permite navegar hasta un elemento dentro del documento XML y probarlo para determinar si existe una condición concreta. Cuando se la especifica como parte de la cláusula WHERE,XMLExistsrestringe los resultados devueltos a aquellas filas que contengan un documento XML con el valor de elemento XML específico (es decir, cuando el valor especificado da como resultado "true").

Veamos un problema de consulta de muestra planteado anteriormente. Imaginemos que fuera necesario localizar los nombres de todos los clientes que viven en un código postal específico. Como recordará, la tabla "clients" almacena la dirección de los clientes (incluido el código postal) en una columna XML. (Ver listado 3.) Usando XMLExists, es posible buscar el código postal de destino en la columna XML y restringir el conjunto de resultados en consecuencia. La siguiente consulta SQL/XML devuelve los nombres de los clientes que viven en el código postal 95116:

Listado 7. Restricción de resultados en función de un valor de elemento XML
select
                name from clients where xmlexists('$c/Client/Address[zip="95116"]' passing
                clients.contactinfo as "c")

La primera línea es una cláusula SQL que especifica que solamente se desea recuperar información de la columna "name" de la tabla "clients". La cláusula WHERE invoca la función XMLExists, especificando una expresión XPath que solicita a DB2 que navegue hasta el elemento "zip" y busque un valor de 95116. La cláusula "$c/Client/Address" indica la ruta de acceso de la jerarquía de documentos XML donde DB2 puede buscar el elemento "zip". Usando datos accesibles desde el nodo "$c" (que se explicará a la brevedad), DB2 navegará por el elemento "Client" hasta el subelemento "Address" para inspeccionar el código postal (valores "zip"). La línea final resuelve el valor de "$c": es la columna "contactinfo" de la tabla "clients". De este modo, DB2 inspecciona los datos XML contenidos en la columna "contactinfo", navega desde el elemento "Client" raíz hasta "Address" y luego hasta "zip" y determina si el cliente vive en el código postal de destino. Si es así, la función XMLExists da como resultado "true" y DB2 devuelve el nombre del cliente asociado con esa fila.

Es un error habitual formular el predicado de consulta XMLExists, como se puede ver en el listado 8.

Listado 8. Sintaxis incorrecta para restringir resultados en función de un valor de elemento XML
 select name from clients where
                xmlexists('$c/Client/Address/zip="95116" ' passing clients.contactinfo as
                "c")

Si bien esta consulta se ejecutará con éxito, no restringirá los resultados a los clientes que vivan en el código postal 95116. (Esto se debe a la semántica especificada en el estándar; no es algo exclusivo de DB2). Para restringir los resultados a aquellos clientes que vivan en el código postal 95116, es necesario usar la sintaxis indicada en el listado 7.

Tal vez desee saber cómo se puede incluir una consulta que restrinja datos XML en una aplicación. Si bien este artículo no tratará temas de desarrollo de aplicaciones en detalle, incluye un ejemplo simple de Java que usa un marcador de parámetro dentro de una instrucción SQL/XML para restringir los resultados a información de clientes que vivan en un determinado código postal.

"Proyección" de valores de elementos XML

Analicemos una situación un tanto diferente, en la que se busca proyectar valores XML en el conjunto de resultados devueltos. En otras palabras, se busca recuperar uno o más valores de elementos de los documentos XML. Existen múltiples maneras de hacerlo. En primer lugar, usemos la función XMLQuery para recuperar un valor de un elemento y luego usemos la función XMLTable para recuperar valores de múltiples elementos y asignarlos a columnas de un conjunto de resultados SQL.

Consideremos la solución para el problema planteado más arriba: cómo crear un informe que enumere las direcciones de correo electrónico de los clientes "Gold". La consulta del listado 9 invoca la función XMLQuery para realizar esta tarea:

Listado 9. Recuperación de información de correo electrónico de clientes calificados
select xmlquery('$c/Client/email' passing contactinfo as
                "c") from clients where status = 'Gold'

La primera línea especifica que se busca devolver valores del subelemento "email" del elemento "Client" raíz. La segunda y tercera líneas indican dónde DB2 puede buscar esta información: en la columna "contactinfo" de la tabla "clients". La cuarta línea restringe aún más la consulta indicando que el único interés son las direcciones de correo electrónico de los clientes "Gold". Esta consulta devolverá un conjunto de elementos XML y valores. Por ejemplo, si hubiera 500 clientes "Gold" con una dirección de correo electrónico cada uno, se obtendría un conjunto de resultados de una columna con 500 filas, como se puede ver en el listado 10:

Listado 10. Resultados de muestra de la consulta anterior
1--------------------------------------------<email>user5976@anyprovider.com</email>.
                . . <email>someID@yahoo.com</email>

Si los clientes "Gold" tienen múltiples direcciones de correo electrónico, es posible indicarle a DB2 que devuelva solo la dirección principal (es decir, la primera dirección de correo electrónico del documento "contactinfo" del cliente). También se puede modificar la expresión XPath en la primera línea de la consulta a tal efecto:

Listado 11. Recuperación de la primera dirección de correo electrónico de cada cliente calificado
select xmlquery('$c/Client/email[1]' passing contactinfo as
                "c") from clients where status = 'Gold'

Por último, si no tiene la dirección de correo electrónico de alguno de los clientes "Gold", es posible escribir una consulta a fin de excluir los valores nulos del conjunto de resultados. Para ello, modifique la consulta anterior agregando otro predicado a la cláusula WHERE para determinar si falta información de correo electrónico. Usted ya conoce la función SQL/XML que permite hacer esto:XMLExists. El listado 12 muestra cómo se puede reescribir la consulta anterior dejando afuera las filas de clientes "Gold" cuya información de contacto (almacenada como XML) carece de una dirección de correo electrónico:

Listado 12. Recuperación de la primera dirección de correo electrónico de cada cliente calificado con al menos una dirección de correo electrónico
select
                xmlquery('$c/Client/email[1]' passing contactinfo as "c") 
                from clients where status
                = 'Gold' and xmlexists('$c/Client/email' passing contactinfo as "c")

Analicemos una situación un tanto diferente, en la que es necesario recuperar múltiples valores de elementos XML.XMLTablegenera resultados tabulares de datos almacenados en columnas XML y es muy útil para proporcionarles a los programadores una vista "relacional" de los datos XML. Al igual queXMLExists y XMLQuery, la función XMLTable hace que DB2 navegue por la jerarquía de documentos XML para buscar los datos de interés. Sin embargo,XMLTabletambién incluye cláusulas para asignar los datos XML a columnas de un conjunto de resultados de tipos de datos SQL.

Observe la siguiente consulta (listado 13), que proyecta columnas de datos relacionales y datos XML almacenados en la tabla "items". (Ver listado 2 para hacer un repaso de la tabla "items"). Los ID de comentario, los ID de cliente y los mensajes se almacenan en documentos XML, en la columna "comments". Los nombres de los elementos están almacenados en una columna VARCHAR de SQL.

Listado 13. Recuperación de múltiples elementos XML y conversión a tipo de datos SQL tradicionales
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

La primera línea especifica las columnas que se incluirán en el conjunto de resultados. Las columnas encerradas por comillas y precedidas por la variable "t" están basadas en valores de elementos XML, como se puede ver en las siguientes líneas de la consulta. La segunda línea invoca la función XMLTable a fin de especificar la columna XML de DB2 que contenga los datos de destino ("i.comments") y la ruta de acceso dentro de los documentos XML de la columna donde se ubican los elementos de interés (dentro del subelemento "Comment" del elemento "Comments" raíz). La cláusula "columns", que abarca las líneas 3-5, identifica los elementos XML específicos que se asignarán a columnas de resultados en el conjunto de resultados SQL, especificado en la línea 1. Una parte de este mapeo implica especificar los tipos de datos en que se convertirán los valores de elementos XML. En este ejemplo, todos los datos XML se convierten en tipos de datos SQL tradicionales.

La figura 2 muestra los resultados de muestra derivados de la ejecución de esta consulta. Como se puede observar, los resultados consisten en un conjunto de resultados simple. Observe que los nombres de las columnas están escritos en mayúsculas, un comportamiento habitual de SQL.

Figura 2. Resultados de muestra de la consulta con función XMLTable
Resultados de muestra de la consulta con función XMLTable

Si así lo desea, puede usar XMLTable para crear conjuntos de resultados que también incluyan columnas XML. Por ejemplo, la siguiente instrucción genera un conjunto de resultados similar al anterior, con la salvedad de que los datos de "Message" están contenidos en una columna XML en vez de una columna VARCHAR de SQL.

Listado 14. Recuperación de múltiples elementos XML y conversión a tipos de datos SQL tradicionales o 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

Creación de vistas relacionales de datos XML

Como es de esperar, las funciones SQL/XML también se pueden usar para definir vistas. Esto es de particular utilidad si desea entregarles a los programadores de la aplicación SQL un modelo relacional de los datos XML nativos.

La creación de una vista relacional de datos en una columna XML no es mucho más complicada que la proyección de valores de elementos XML. Simplemente escriba una instrucción SELECT de SQL/XML que invoque la función XMLTable y úsela como base de definición de la vista. El ejemplo del listado 15 crea una vista basada en la información de las columnas XML y no XML de la tabla "items" (similar a la consulta del listado 13).

Listado 15. Creación de una vista en función de los resultados 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;

Si bien es fácil crear vistas relacionales de datos de columnas XML, se recomienda considerar su uso muy cuidadosamente si no se dispone de la versión 9.7. Antes de V9.7, DB2 no usaba índices de columnas XML cuando se emitían consultas con relación a tales vistas. Así, si se indizaba el elemento ResponseRequested y se emitía una consulta SQL que restringía los resultados de la columna "mustrespond" a un cierto valor, DB2 leería todos los documentos XML y buscaría el valor "ResponseRequested" adecuado. A menos que exista una pequeña cantidad de datos, esto haría más lento el rendimiento en tiempo de ejecución. Por eso, si no dispone de la versión 9.7, en la que DB2 usa índices XML con predicados SQL, tenga mucho cuidado con este tema.

Combinación de datos XML y relacionales

A esta altura se estará preguntando si es posible combinar datos XML con datos no XML data (por ejemplo, datos relacionales basados en tipos SQL tradicionales). DB2 le permite hacer esto en una única instrucción SQL/XML. Si bien existen diferentes maneras de formular estas combinaciones, según los requisitos de la carga de trabajo y el esquema de base de datos, se analizará un solo ejemplo. Tal vez se sorprenda cuando se entere de que ya cuenta con suficientes conocimientos de SQL/XML para realizar esta tarea.

Como recordará, la columna XML de la tabla "items" contiene un elemento "CustomerID". Esto puede servir de clave de combinación para la columna "id" basada en enteros de la tabla "clients". Por eso, si desea obtener un informe con el nombre y el estado de los clientes que hicieron comentarios de uno o más productos, es necesario combinar los valores de los elementos XML de una tabla con los valores enteros SQL de otra. Otra forma de realizar esta tarea es usar la función XMLExists, como se puede ver en el listado 16:

Listado 16. Combinación de datos XML y no 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")

La primera línea identifica las columnas SQL que se incluirán en el conjunto de resultados de la columna y las tablas de origen a las que se hace referencia en la consulta. La segunda línea incluye la cláusula de combinación. En este caso,XMLExistsdetermina si el valor "CustomerID" de un origen de destino es igual a un valor derivado de otro origen de destino. La tercera línea especifica estos orígenes: el primero es la columna XML "comments" de la tabla "items" y el segundo es la columna de enteros "id" de la tabla "clients". Así, si los clientes hicieron cometarios de algún elemento y se dispone de información sobre este cliente en la tabla "clients", la expresión XMLExists dará como resultado "true" y la información del nombre y estado del cliente quedará incluida en el informe.

Uso de expresiones "FLWOR" en SQL/XML

Si bien se analizaron solo algunas de las funciones, SQL/XML ofrece muchas capacidades eficaces de consulta de datos XML y de integración de esos datos con datos relacionales. En realidad, ya vimos algunos de estos ejemplos, pero a continuación examinaremos algunos otros.

Tanto la función XMLExists como la función XMLQuery permiten incorporar XQuery en SQL. Los ejemplos anteriores muestran cómo usar estas funciones con expresiones XPath simples para navegar por una porción de un documento XML de interés. Ahora consideremos un ejemplo sencillo en el que se incluye XQuery en las consultas SQL.

XQueries puede contener algunas de las siguientes cláusulas, o todas: "for", "let", "where", "order by" y "return." En conjunto, forman expresiones FLWOR(pronúnciese como flower). Para los programadores SQL, puede resultar conveniente incorporar XQueries en las listas SELECT para extraer (o proyectar) fragmentos de documentos XML en los conjuntos de resultados. Esta no es la única forma en que se puede usar la función XMLQuery, pero es el escenario contemplado en este artículo (un futuro artículo de la serie tratará XQuery con mayor profundidad).

Imagine que desea recuperar el nombre y la dirección de correo electrónico principal de sus clientes "Gold". En algunos aspectos, esta tarea es similar a que realizamos anteriormente (ver listado 11), cuando analizábamos la forma de proyectar valores de elementos XML. En este caso, se pasa XQuery (con cláusulas "for" y "return") como entrada de la función XMLQuery:

Listado 17. Recuperación de datos XML con cláusulas "for" y "return" de XQuery
select name, xmlquery('for $e in $c/Client/email[1] return $e'
                passing contactinfo as "c") from clients where status = 'Gold'

La primera línea especifica los nombres de clientes y los resultados de la función XMLQuery que se incluirán en el conjunto de resultados. La segunda línea indica que se devolverá el primer subelemento "email" del elemento "Client". La tercera línea identifica el origen de los datos XML: la columna "contactinfo". La línea 4 indica que esta columna está en la tabla "clients". Por último, la quinta línea indica que solamente los son de interés los clientes "Gold".

Como este ejemplo es tan simple, sería posible escribir la misma consulta. También es posible escribir la misma consulta de una manera más compacta:

Listado 18. Reescritura de la consulta anterior de una manera más compacta
select
                name, xmlquery('$c/Client/email[1]' 
                passing contactinfo as "c") 
                from clients where
                status = 'Gold'

Sin embargo, la cláusula return de XQuery permite transformar los resultados XML en la medida de lo necesario. Por ejemplo, es posible extraer valores de elementos de correo electrónico y publicarlos como HTML. La siguiente consulta generará un conjunto de resultados en que la primera dirección de correo electrónico de cada uno de los clientes "Gold" es devuelta como párrafo HTML.

Listado 19. Recuperación de datos XML y transformación en HTML
select xmlquery('for
                $e in $c/Client/email[1]/text() return <p>{$e}</p>'
                passing contactinfo as "c") from clients where status = 'Gold'

La primera línea indica que el interés está puesto en la representación textual de la primera dirección de correo electrónico de los clientes calificados. La segunda línea especifica que esta información debe estar encerrada por etiquetas de párrafos HTML antes de su devolución. En particular, las llaves ( { } ) indican a DB2 que evalúe la expresión encerrada (en este caso, "$e") en vez de considerarla una cadena literal. Si se omiten las llaves, DB2 devolvería un conjunto de resultados que contendría "<p>$e</p>" para cada uno de los registros de clientes calificados.

Publicación de datos relacionales como XML

Hasta ahora, nos hemos centrado en diferentes formas de consultar, extraer o transformar datos contenidos dentro de una columna XML de DB2. Y, como ya se analizó, estas capacidades están disponibles en SQL/XML.

SQL/XML también proporciona otras características de gran utilidad. Entre ellas se encuentra la capacidad de convertir o publicar datos relacionales como XML. En este artículo se analizan solamente tres de estas funciones SQL/XML:XMLElement,XMLAgg y XMLForest.

XMLElement permite convertir datos almacenados en columnas SQL tradicionales en fragmentos XML. Es decir, se pueden construir elementos XML (con o sin atributos XML) a partir de los datos SQL básicos. El siguiente ejemplo usa la función XMLElement para crear una serie de elementos, cada uno de los cuales contiene subelementos de los valores ID, nombre de marca y referencia de almacén ("sku") obtenidos de la tabla "items":

Listado 20. Uso de XMLElement para publicar datos relacionales como XML
select
                xmlelement (name "item", xmlelement (name "id", id), 
                xmlelement (name "brand",
                brandname), xmlelement (name "sku", sku) ) from items where srp < 100

La ejecución de esta consulta generará resultados similares a:

Listado 21. Resultados de muestra de la consulta anterior
<item><id>4272</id><brand>Classy<
                /brand><sku>981140</sku></item>.
                . . <item> <id>1193</id>
                <brand>Natural</brand>
                <sku>557813</sku> </item>

Es posible combinar XMLElement con otras funciones de publicación SQL/XML para generar y agrupar valores XML, anidándolos en jerarquías como usted desee. El ejemplo del listado 22 usa XMLElement para crear elementos customerList cuyo contenido esté agrupado por valores en la columna "status". Para cada registro "customerList" la función XMLAgg devuelve una secuencia de elementos de cliente, cada uno de los cuales incluye subelementos basados en las columnas "name" y "status". Además, se puede observar que los valores de elementos de cliente están ordenados por nombre de cliente.

Listado 22. Agregación y agrupación de datos
select xmlelement(name "customerList",
                xmlagg (xmlelement (name "customer", 
                xmlforest (name as "fullName", status as
                "status") ) order by name ) ) from clients group by status

Supongamos que la tabla "clients" contiene tres valores "status" distintos: "Gold", "Silver" y "Standard". La ejecución de la consulta anterior hará que DB2 devuelva tres elementos customerList, cada uno de los cuales puede contener múltiples subelementos que, a su vez, contienen información de nombre y de estado. Así, los resultados serán similares a:

Listado 23. Resultados de muestra de la 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>

Operaciones de actualización y eliminación

Si bien el interés de este artículo está puesto en la búsqueda y recuperación de datos almacenados en columnas XML usando SQL, vale la pena dedicar unos minutos a otras dos tareas comunes: la actualización y la eliminación de datos en las columnas XML.

DB2 9 permitió actualizar y eliminar datos XML usando instrucciones SQL y SQL/XML. De hecho, como el borrador inicial del estándar XQuery no contemplaba estas cuestiones, los usuarios de DB2 dependían de SQL para realizar estas tareas. Sin embargo, W3C trabajaba en el desarrollo de XQuery Update Facility, una facilidad implementada en DB2 9.5. La incorporación de XQuery Update Facility (inicialmente llamada TRANSFORM) simplificó mucho los atributos y elementos de actualización de un documento XML y estableció un estándar a tal efecto. El estado actual de XQuery Update Facility es candidata a recomendación.

Actualización de datos XML

Si bien DB2 9 permitía actualizar una columna XML con una instrucción UPDATE de SQL o mediante el uso de un procedimiento almacenado suministrado por el sistema (DB2XMLFUNCTIONS.XMLUPDATE), con DB2 9.5, es posible usar la nueva XQuery Update Facility. Esta facilidad permite actualizar, insertar, eliminar y crear un nuevo elemento o atributo dentro de un documento XML existente sin necesidad de volver a crear un documento completo. La facilidad Update también se puede usar para modificar múltiples nodos en la misma transacción.

Por ejemplo, si desea emitir una instrucción UPDATE para cambiar la dirección de correo electrónico de la información de contacto de un cliente específico, simplemente tendrá que suministrar la nueva dirección de correo electrónico.

Observe la siguiente instrucción:

Listado 24. Instrucción UPDATE de muestra
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;

Las cláusulas "copy $new", "modify do replace of $new" y "return $new" son cláusulas obligatorias de la facilidad XQuery Update. Para conocer mejor la sintaxis exacta y las opciones correspondientes, consulte la sección Recursos. Hemos incluido el sitio de la especificación XQuery, así como un artículo de developerWorks que ofrece más detalles sobre XQuery Update Facility.

Eliminación de datos XML

La eliminación de filas que contienen columnas XML es un proceso sencillo. La instrucción DELETE de SQL permite identificar (o restringir) las filas que se busca eliminar mediante una cláusula WHERE. Esta cláusula puede incluir predicados simples a fin de identificar valores de columnas no XML o funciones SQL/XML a fin de identificar valores de elementos XML contenidos en columnas XML.

Por ejemplo, de esta manera se puede borrar toda la información del ID de cliente 3227:

Listado 25. Eliminación de datos de un cliente específico
delete from clients where
                id = 3227

¿Recuerda cómo se pueden restringir las instrucciones SELECT de SQL para que se devuelvan solamente las filas de aquellos clientes que viven en el código postal 95116? Si lo recuerda, podrá aplicar muy fácilmente sus conocimientos a la eliminación de filas que sigan a esos clientes. A continuación se demuestra cómo hacerlo usando XMLExists:

Listado 26. Eliminación de datos de clientes con un código postal específico
delete
                from clients where xmlexists('$c/Client/Address[zip="95116"]' passing
                clients.contactinfo as "c");

Indización

Por último, vale la pena destacar que es posible crear índices XML especializados para acelerar el acceso a datos almacenados en columnas XML. Como este es un artículo introductorio y los datos de muestra son limitados, no analizaremos este tema. Sin embargo, en entornos de producción, la definición de índices adecuados puede ser de vital importancia para alcanzar un rendimiento óptimo. La sección Recursos de este artículo lo ayudará a conocer mejor la nueva tecnología de indización de DB2.


Resumen

En este artículo se trataron numerosos puntos del tema y se resaltaron diversos aspectos centrales de SQL/XML y la manera de usar esta tecnología para consultar datos en columnas XML. Por supuesto que con las funciones SQL y SQL/XML se pueden hacer muchas más cosas de las que se analizaron aquí. Este artículo incluye un ejemplo simple de Java que demuestra cómo se pueden usar marcadores de parámetro con SQL/XML para consultar datos en columnas XML. En un futuro artículo se examinarán cuestiones de desarrollo de aplicaciones con mayor detalle. Sin embargo, el próximo artículo tratará ciertos aspectos interesantes de XQuery, un nuevo lenguaje de consulta compatible con DB2 9.

Agradecimientos

La autora desea agradecer a George Lapis, Matthias Nicola, Sriram Padmanabhan, Gary Robinson, Hardeep Singh y Bert Van der Linden por su ayuda en este artículo.

Recursos

Aprender

Obtener los productos y tecnologías

  • Genere su próximo proyecto de desarrollo con el software de prueba de IBM, disponible para su descarga directa desde developerWorks.
  • Ahora puede usar DB2 de manera gratuita. Descargue DB2 Express-C, una versión sin cargo de DB2 Express Edition para la comunidad que ofrece las mismas funciones centrales de datos que DB2 Express Edition y proporciona una base sólida para generar e implementar aplicaciones.

Comentar

Comentarios

developerWorks: Ingrese

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


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

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

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Information mgmt, Rational
ArticleID=487573
ArticleTitle=Comience a usar DB2 9 pureXML ya mismo, parte 3: Consulte datos XML de DB2 con SQL
publish-date=05042010