IBM i Versión 7.2
Base de datos Programación SQL XML
IBM i Versión 7.2
Base de datos Programación SQL XML
Aviso Antes de utilizar esta información y el producto al que da soporte, lea la información contenida en “Avisos” en la página 231.
Esta edición se aplica a IBM i 7.1 (producto número 5770-SS1) y a todos los releases y modificaciones subsiguientes hasta que se indique lo contrario en nuevas ediciones. Esta versión no se ejecuta en todos los modelos de sistema con conjunto reducido de instrucciones (RISC) ni tampoco se ejecutan en los modelos CISC. Este documento puede contener referencias al código interno bajo licencia. El código interno bajo licencia (LIC) es código máquina y se licencia bajo los términos del Acuerdo de licencia de IBM para Código máquina. © Copyright IBM Corporation 2012, 2014.
Contenido Programación SQL XML . . . . . . . . 1 Novedades de IBM i 7.2 . . . . . . . . . . 1 Cómo leer los diagramas de sintaxis . . . . . . 1 Archivo PDF de Programación SQL XML . . . . . 3 Sentencias SQL y funciones SQL/XML . . . . . 3 Visión general de la entrada y salida XML . . . 4 Comparación entre XML y los modelos relacionales . . . . . . . . . . . . . . 5 Guía de aprendizaje de XML . . . . . . . . 7 Ejercicio 1: Crear una tabla que puede almacenar datos XML . . . . . . . . . 7 Ejercicio 2: Insertar documentos XML en columnas de tipo XML . . . . . . . . . 7 Ejercicio 3: Actualizar documentos XML almacenados en una columna XML . . . . . 8 Ejercicio 4: Validar documentos XML con respecto a esquemas XML . . . . . . . . 9 Ejercicio 5: Transformación con hojas de estilo XSLT . . . . . . . . . . . . . . 11 Inserción de datos XML . . . . . . . . . 14 Adición de columnas XML a tablas existentes 14 Inserción en columnas XML . . . . . . . 14 Análisis XML . . . . . . . . . . . . 15 Funciones de publicación de SQL/XML para construir valores XML . . . . . . . . . . 17 Ejemplo: Construir un documento XML con valores de una sola tabla . . . . . . . . 18 Ejemplo: Construir un documento XML con valores de varias tablas . . . . . . . . 19 Ejemplo: Construir un documento XML con los valores de filas de tabla que contienen elementos nulos . . . . . . . . . . . 19 Ejemplo: Transformación con hojas de estilo XSLT . . . . . . . . . . . . . . 20 Ejemplo: Utilización de XSLT como motor de formato. . . . . . . . . . . . . . 22 Ejemplo: Utilización de XSLT para el intercambio de datos . . . . . . . . . 23 Ejemplo: Utilización de XSLT para eliminar espacios de nombres . . . . . . . . . 25 Consideraciones importantes para la transformación de documentos XML . . . . 28 Manejo de caracteres especiales en funciones de publicación de SQL/XML . . . . . . 28 Serialización de XML . . . . . . . . . 29 Diferencias en un documento XML tras el almacenamiento y recuperación. . . . . . 31 Tipos de datos para el archivado de documentos XML . . . . . . . . . . 31 Utilización de XMLTABLE para hacer referencia al contenido XML como una tabla relacional . . 32 Ejemplo: Utilizar XMLTABLE para manejar elementos que faltan . . . . . . . . . 33 Ejemplo: Utilizar XMLTABLE para crear un subconjunto de datos de resultado. . . . . 34 © Copyright IBM Corp. 2012, 2014
Ejemplo: Utilizar XMLTABLE para manejar varios valores. . . . . . . . . . . . Ejemplo: Utilizar XMLTABLE con espacios de nombres . . . . . . . . . . . . . Ejemplo: Numerar filas de resultados para XMLTABLE . . . . . . . . . . . . Actualización de datos XML . . . . . . . . Supresión de datos XML de tablas . . . . . Repositorio de esquemas XML . . . . . . . Soporte de lenguajes de programación de aplicaciones . . . . . . . . . . . . . Inserciones y actualizaciones de columnas XML en aplicaciones CLI . . . . . . . . Recuperación de datos XML en aplicaciones CLI . . . . . . . . . . . . . . . Declaración de variables del lenguaje principal XML en aplicaciones de SQL incorporado . . Ejemplo: Cómo hacer referencia a variables host XML en aplicaciones de SQL incorporado . . . . . . . . . . . Recomendaciones para el desarrollo de aplicaciones de SQL incorporado con XML . Identificación de valores XML en un SQLDA . . . . . . . . . . . . . Java . . . . . . . . . . . . . . . Datos XML en aplicaciones JDBC . . . . Datos XML en aplicaciones SQLJ . . . . Rutinas . . . . . . . . . . . . . . Soporte de XML en procedimientos SQL. . Soporte para el tipo de datos XML en rutinas externas . . . . . . . . . . Codificación de datos XML . . . . . . . . Consideraciones sobre codificación al almacenar o pasar datos XML . . . . . . Consideraciones de codificación para la entrada de datos XML en una base de datos . . . . . . . . . . . . . Consideraciones de codificación para la recuperación de datos XML de una base de datos . . . . . . . . . . . . . Consideraciones de codificación para pasar datos XML en parámetros de rutinas . . . Consideraciones de codificación para datos XML en aplicaciones JDBC y SQLJ. . . . Efectos de la codificación y serialización XML sobre la conversión de datos. . . . . . . Escenarios de codificación para la entrada de datos XML codificados internamente en una base de datos . . . . . . . . . Escenarios de codificación para la entrada de datos XML codificados externamente en una base de datos . . . . . . . . . Escenarios de codificación para la recuperación de datos XML con serialización implícita . . . . . . . .
34 36 39 39 40 40 41 42 43 44
45 46 46 46 46 52 55 55 56 60 60
60
60 61 61 61
62
63
65
iii
Escenarios de codificación para la recuperación de datos XML con XMLSERIALIZE explícita . . . . . . . 68 Correlaciones de nombres de codificación con los CCSID efectivos para datos XML almacenados . . . . . . . . . . . . 70 Correlaciones de CCSID con nombres de codificación para datos de salida XML serializados . . . . . . . . . . . . 70 Descomposición de esquemas XML anotados . . . 70 Descomposición de documentos XML con esquemas XML anotados . . . . . . . . . 71 Registro y habilitación de esquemas XML para la descomposición . . . . . . . . . . . . 71 Orígenes de descomposición de esquemas XML anotados . . . . . . . . . . . . . . 71 anotaciones de descomposición XML . . . . . 72 Especificación y ámbito de las anotaciones de descomposición XML . . . . . . . . . 72 Anotaciones como atributos . . . . . . . 73 Anotaciones como elementos hijo estructurados . . . . . . . . . . . . 73 Anotaciones globales . . . . . . . . . 73 Anotaciones de descomposición XML Resumen . . . . . . . . . . . . . 73 Anotación de descomposición db2-xdb:defaultSQLSchema . . . . . . . 74 Anotación de descomposición db2-xdb:rowSet 75 Anotación de descomposición db2-xdb:table 80 Anotación de descomposición db2-xdb:column 82 Anotación de descomposición db2-xdb:locationPath . . . . . . . . . 84 Anotación de descomposición db2-xdb:expression . . . . . . . . . . 87 Anotación de descomposición db2-xdb:condition . . . . . . . . . . 90 Anotación de descomposición db2-xdb:contentHandling . . . . . . . . 93 Anotación de descomposición db2-xdb:normalization. . . . . . . . . 97 Anotación de descomposición db2-xdb:order 99 Anotación de descomposición db2-xdb:truncate . . . . . . . . . . 101 Anotación de descomposición db2-xdb:rowSetMapping . . . . . . . 103 Anotación de descomposición db2-xdb:rowSetOperationOrder . . . . . 105 Palabras clave para la descomposición de esquemas XML anotados . . . . . . . 106 Tratamiento de las secciones CDATA en la descomposición del esquema XML anotado . . 107 Valores NULL y series vacías en la descomposición de esquemas XML anotados . . 107 Lista de comprobación para la descomposición de esquemas XML anotados . . . . . . . 108 Ejemplos de correlaciones en la descomposición de esquemas XML anotados . . . . . . . 109 Anotaciones de tipos complejos derivados 109 Ejemplo de anotación de descomposición: Correlación con una columna XML . . . . 115
iv
IBM i: Programación SQL XML
Ejemplo de anotación de descomposición: Un valor correlacionado con una sola tabla que genera una sola fila . . . . . . . . . Ejemplo de anotación de descomposición: Un valor correlacionado con una sola tabla que genera varias filas . . . . . . . . . . Ejemplo de anotación de descomposición: Un valor correlacionado con varias tablas . . . Ejemplo de anotación de descomposición: Agrupación de varios valores correlacionados con una sola tabla . . . . . . . . . . Ejemplo de anotación de descomposición: Varios valores de contextos diferentes correlacionados con una sola tabla . . . . Compatibilidad de tipos de esquema XML con tipos SQL para la descomposición de esquemas anotados . . . . . . . . . Límites y restricciones para la descomposición de esquemas XML anotados . Esquema para las anotaciones de descomposición XML. . . . . . . . . Modelo de datos XML . . . . . . . . . . Secuencias y elementos . . . . . . . . . Valores atómicos . . . . . . . . . . . Nodos . . . . . . . . . . . . . . . Nodos de documento. . . . . . . . . Nodos de elemento . . . . . . . . . Nodos de atributo . . . . . . . . . . Nodos de texto . . . . . . . . . . . Nodos de instrucción de proceso . . . . . Nodos de comentario. . . . . . . . . Generación de modelos de datos . . . . . . Valores XML en SQL . . . . . . . . . . Visión general de XPath . . . . . . . . . . Sensibilidad a las mayúsculas y minúsculas en DB2 XPath . . . . . . . . . . . . . Espacios en blanco en DB2 XPath . . . . . Comentarios en DB2 XPath . . . . . . . . Juego de caracteres . . . . . . . . . . Ordenación predeterminada . . . . . . . Espacios de nombres XML y nombres calificados en DB2 XPath . . . . . . . . Sistema de tipos de XPath . . . . . . . . Visión general del sistema de tipos . . . . Funciones de constructor para tipos incorporados . . . . . . . . . . . Tipos de datos genéricos . . . . . . . xs:anyType . . . . . . . . . . . xs:anySimpleType . . . . . . . . . xs:anyAtomicType . . . . . . . . . Tipos de datos para datos sin tipo . . . . xs:untyped . . . . . . . . . . . xs:untypedAtomic . . . . . . . . . xs:string . . . . . . . . . . . . . Tipos de datos numéricos . . . . . . . xs:decimal . . . . . . . . . . . xs:double . . . . . . . . . . . . xs:integer . . . . . . . . . . . . Límites de rango para tipos numéricos xs:boolean . . . . . . . . . . . . Tipos de datos de fecha y hora . . . . .
116
118 119
121
123
124 131 132 133 133 134 134 135 136 138 138 139 139 140 141 142 144 144 145 145 145 146 147 147 147 148 148 148 148 148 148 149 149 149 149 150 150 151 151 152
xs:date . . . . . . . . . . xs:time . . . . . . . . . . xs:dateTime . . . . . . . . . xs:duration . . . . . . . . . xs:dayTimeDuration . . . . . . xs:yearMonthDuration . . . . . Conversiones entre tipos de datos de esquema XML . . . . . . . . . Expresiones y prólogos XPath . . . . . Prólogos . . . . . . . . . . . Declaraciones de espacio de nombres Declaraciones de espacio de nombres predeterminado . . . . . . . Evaluación y proceso de expresiones . Atomización. . . . . . . . . Promoción de tipo. . . . . . . Sustitución de subtipo . . . . . Expresiones primarias . . . . . . Literales . . . . . . . . . . Referencias de variable en DB2 XPath Expresión entre paréntesis . . . . Expresiones de elemento de contexto Llamadas de función . . . . . . Expresiones de vía de acceso . . . . Pasos de eje . . . . . . . . . Sintaxis abreviada para expresiones de de acceso . . . . . . . . . . Expresiones de filtro . . . . . . . Expresiones aritméticas . . . . . . Expresiones de comparación . . . . Comparaciones genéricas . . . . Expresiones lógicas . . . . . . . Expresiones regulares. . . . . . . Descripciones de funciones XPath . . . Función fn:abs . . . . . . . . . Función fn:adjust-date-to-timezone . . Función fn:adjust-dateTime-to-timezone Función fn:adjust-time-to-timezone . . Función fn:boolean . . . . . . . Función fn:compare . . . . . . . Función fn:concat . . . . . . . . Función fn:contains . . . . . . . Función fn:count . . . . . . . . Función fn:current-date . . . . . . Función fn:current-dateTime . . . . Función db2-fn:current-local-date . . . Función db2-fn:current-local-dateTime . Función db2-fn:current-local-time. . . Función fn:current-time . . . . . . Función fn:data. . . . . . . . . Función fn:dateTime . . . . . . . Función fn:day-from-date . . . . .
. . . . . .
. . . . . .
152 152 153 154 156 157
. . . .
. . . .
158 160 161 161
. . . . . . . . . . . . . . . . . . . . . . . . . . vía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
162 163 163 163 164 164 164 165 166 166 167 167 168 174 175 175 178 178 179 180 183 187 188 189 191 192 193 194 194 195 195 196 196 196 197 197 198 198 199
Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función Función
fn:day-from-dateTime. . . fn:days-from-duration . . fn:distinct-values . . . . fn:exists . . . . . . . fn:hours-from-dateTime . . fn:hours-from-duration . . fn:hours-from-time . . . fn:implicit-timezone . . . fn:last . . . . . . . . fn:local-name . . . . . db2-fn:local-timezone . . . fn:lower-case . . . . . fn:matches . . . . . . fn:max. . . . . . . . fn:min . . . . . . . . fn:minutes-from-dateTime . fn:minutes-from-duration . fn:minutes-from-time . . . fn:month-from-date . . . fn:month-from-dateTime . . fn:months-from-duration . fn:name . . . . . . . fn:normalize-space. . . . fn:not . . . . . . . . fn:position . . . . . . fn:replace . . . . . . . fn:round . . . . . . . fn:seconds-from-dateTime . fn:seconds-from-duration . fn:seconds-from-time . . . fn:starts-with . . . . . fn:string . . . . . . . fn:string-length . . . . . fn:substring . . . . . . fn:sum. . . . . . . . fn:timezone-from-date . . fn:timezone-from-dateTime . fn:timezone-from-time . . fn:tokenize . . . . . . fn:translate . . . . . . fn:upper-case . . . . . fn:year-from-date . . . . fn:year-from-dateTime . . fn:years-from-duration . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
199 200 200 201 202 202 203 203 204 205 206 206 207 208 209 210 210 211 212 212 213 213 215 215 216 217 218 219 219 220 220 221 222 222 223 223 224 225 225 227 228 228 229 229
Avisos . . . . . . . . . . . . . . 231 Información de interfaz de programación . Marcas registradas. . . . . . . . . Términos y condiciones . . . . . . .
. . .
. . .
. 233 . 233 . 233
Índice. . . . . . . . . . . . . . . 235
Contenido
v
vi
IBM i: Programación SQL XML
Programación SQL XML DB2 para IBM® i proporciona soporte para almacenar y recuperar datos XML utilizando el lenguaje de consulta estructurado (SQL). Los objetos definidos mediante SQL, como por ejemplo tablas, funciones y procedimientos, pueden utilizar el tipo de datos XML para definiciones de columna, parámetro y variable. Además de un tipo de datos XML, existen funciones incorporadas y procedimientos que puede utilizarse para generar documentos XML y recuperar la totalidad o parte de un documento XML. Nota: Por el hecho de utilizar los ejemplos de código, acepta los términos de la “Información sobre licencia de código y exención de responsabilidad” en la página 230.
Novedades de IBM i 7.2 Conozca la información nueva o que ha cambiado sustancialmente en el temario de programación SQL XML. | |
La colección de temas de programación SQL XML es nueva. Incluye todas la información de XML que anteriormente se encontraba en el temario Programación SQL.
Cómo ver las novedades o los cambios realizados Para facilitar la visualización de los cambios técnicos realizados, el centro de información utiliza: v La imagen , que señala dónde empieza la información nueva o cambiada. v La imagen para marcar el final de la información nueva o modificada. En los archivos PDF, puede ver barras de revisión (|) en el margen izquierdo de la información nueva o modificada. Para obtener otra información acerca de los cambios y novedades de este release, consulte el Memorándum para los usuarios.
Cómo leer los diagramas de sintaxis Los diagramas de sintaxis utilizados en este manual están sujetos a las normas siguientes. v Lea los diagramas de sintaxis de izquierda a derecha y de arriba abajo, siguiendo el recorrido de la línea. El símbolo ─── indica el principio del diagrama de sintaxis. El símbolo ---? indica que la sintaxis continúa en la línea siguiente. El símbolo ─── indica que la sintaxis continúa de la línea anterior. El símbolo ─── indica el final del diagrama de sintaxis. Los diagramas de unidades sintácticas empiezan con el símbolo |─── y finalizan con el símbolo ───|. v Los elementos obligatorios aparecen en la línea horizontal (la ruta principal). elemento_obligatorio
v Los elementos opcionales se muestran debajo de la ruta principal. elemento_obligatorio
elemento_opcional
© Copyright IBM Corp. 2012, 2014
1
Si un elemento aparece encima de la ruta principal, ese elemento es opcional, no tiene ningún efecto sobre la ejecución de la sentencia y se utiliza sólo a efectos de legibilidad. elemento_opcional elemento_obligatorio
v Si puede elegirse más de un elemento, éstos aparecen verticalmente, en una pila. Si uno de los elementos debe elegirse, un elemento de la pila aparece en la ruta principal. elemento_obligatorio
opción_obligatoria opción_obligatoria
Si la elección de uno de los elementos es opcional, toda la pila aparece debajo de la línea principal. elemento_obligatorio
opción_opcional opción_opcional
Si uno de los elementos es el valor predeterminado, aparecerá encima de la ruta principal y las opciones restantes se mostrarán debajo. opción_predeterminada elemento_obligatorio
opción_opcional opción_opcional
Si un elemento opcional tiene un valor predeterminado cuando no se especifica, el valor predeterminado aparece encima de la ruta principal. elemento_obligatorio
opción_opcional
opción_predeterminada opción_obligatoria opción_obligatoria
opción_opcional
v Una flecha que vuelve a la izquierda, sobre la línea principal, indica un elemento que se puede repetir.
elemento_obligatorio elemento_repetible
Si la flecha de repetición contiene una coma, los elementos repetidos se deben separar mediante comas. , elemento_obligatorio elemento_repetible
Una flecha de repetición encima de una pila indica que los elementos de la pila se pueden repetir. v Las palabras clave aparecen en mayúsculas (por ejemplo FROM). Se deben escribir exactamente tal como se muestran. Las variables aparecen completamente en minúsculas (por ejemplo, nombre-columna). Representan nombres o valores suministrados por el usuario. v Si se muestran signos de puntuación, paréntesis, operadores aritméticos u otros símbolos de este tipo, debe especificarlos como parte de la sintaxis.
2
IBM i: Programación SQL XML
Archivo PDF de Programación SQL XML Puede ver e imprimir un archivo PDF de esta información. Para ver o descargar la versión PDF de este documento, seleccione Programación SQL XML.
Cómo guardar los archivos PDF Para guardar un PDF en la estación de trabajo con el fin de verlo o imprimirlo: 1. En el navegador, pulse el enlace al PDF con el botón derecho del ratón. 2. Pulse la opción que guarda el PDF localmente. 3. Navegue hasta el directorio en el que desee guardar el PDF. 4. Pulse Guardar.
Cómo descargar Adobe Reader Para poder ver o imprimir archivos PDF, debe instalar Adobe Reader en su sistema. Puede descargar una copia gratuita desde el sitio Web de Adobe (http://get.adobe.com/reader/)
.
Sentencias SQL y funciones SQL/XML Muchas sentencias SQL admiten el tipo de datos XML. Esto permite realizar muchas operaciones comunes de base de datos con datos XML, como por ejemplo crear tablas con columnas XML, añadir columnas XML a tablas existentes, crear desencadenantes en tablas con columnas XML e insertar, actualizar o suprimir documentos XML. Un conjunto de funciones, expresiones y especificaciones de SQL/XML soportadas por el servidor de bases de datos DB2 se beneficia plenamente del tipo de datos XML.
Tipo de datos XML El tipo de datos XML puede almacenar un valor XML de hasta 2 GB. Puede especificarse un CCSID para el tipo de datos XML. Si no se especifica un CCSID, se utilizará el valor de la opción QAQQINI SQL_XML_DATA_CCSID. El valor predeterminado para esta opción es 1208 (UTF-8). El tipo de datos XML puede almacenar caracteres de un solo byte y Unicode de doble byte. Una sola fila de una tabla que contenga uno o más valores LOB o XML no puede superar los 3,5 GB. El tipo de datos XML puede especificarse en una tabla particionada. Pueden declararse variables de lenguaje principal XML y localizadores de XML en programas de aplicación. Los localizadores de XML pueden utilizarse para hacer referencia a valores XML. Un valor XML puede captarse en un localizador de XML. Un localizador XML puede pasarse a un procedimiento o función. El localizador puede especificarse como valor en una sentencia INSERT o UPDATE. Las entradas de diario para las columnas XML son iguales que para los LOB. Consulte "Diseño de entradas de diario de columnas LOB" en la colección de temas de programación SQL.
Desarrollo de aplicaciones Varios lenguajes de programación y funciones y procedimientos externos y SQL suministran soporte para el desarrollo de aplicaciones:
Programación SQL XML
3
Soporte de lenguaje de programación El soporte de desarrollo de aplicaciones de XML permite a las aplicaciones combinar XML y almacenamiento y acceso a datos relacionales. Los siguientes lenguajes de programación dan soporte al tipo de datos XML para SQL: v ILE RPG v ILE COBOL v C o C++ (SQL incorporado o CLI de DB2) v Java™ (JDBC o SQLJ) Funciones y procedimientos externos y SQL Los datos XML pueden pasarse a procedimientos SQL y procedimientos externos mediante la inclusión de parámetros de tipo de datos XML en las signaturas de parámetro de CREATE PROCEDURE. También pueden pasarse datos XML a funciones externas y SQL mediante la inclusión de parámetros del tipo de datos XML en las signaturas de parámetro de CREATE FUNCTION. Las características de la rutina SQL existentes dan soporte a la implementación de un flujo de lógica de procedimientos alrededor de sentencias SQL, que genera o utiliza valores XML así como almacenamiento temporal de valores de datos XML en variables.
Administración Las características de XML suministran un repositorio para la gestión de las dependencias de URI de los documentos XML: Repositorio de esquemas XML (XSR) El repositorio de esquemas XML (XSR) es un repositorio para todos los artefactos XML necesarios para procesar documentos de instancia XML almacenados en columnas XML. Almacena esquemas XML referenciados en documentos XML. Puede utilizarse para validar o descomponer documentos de instancia XML.
Herramientas IBM i Navigator incluye soporte para el tipo de datos XML.
Descomposición de esquemas XML anotados Las características de XML permiten almacenar y acceder a los datos XML como documentos XML. Puede haber casos en los que sea necesario acceder a datos XML como datos relacionales. La descomposición de esquemas XML anotados descompone documentos en función de las anotaciones especificadas en un esquema XML.
Visión general de la entrada y salida XML El servidor de bases de datos DB2, que gestiona los datos relacionales y XML, ofrece diversos métodos para la entrada y salida de documentos XML. Los documentos XML se almacenan en columnas definidas con el tipo de datos XML. Cada fila de una columna XML almacena un solo documento XML bien formado. El documento almacenado se mantiene en su formato de documento XML. Las columnas XML pueden definirse en tablas que contengan columnas de otros tipos, que contengan datos relacionales y pueden definirse varias columnas XML para una sola tabla.
Entrada El método que utilice para colocar datos XML en el sistema de bases de datos depende de la tarea que desee realizar:
4
IBM i: Programación SQL XML
Insertar o actualizar Los documentos bien formados se insertan en columnas XML mediante la sentencia SQL INSERT. Un documento está bien formado cuando puede analizarse satisfactoriamente. La validación de los documentos XML durante una operación de inserción o actualización es opcional. Si se efectúa la validación, el esquema XML primero debe registrarse en el repositorio de esquemas XML (XSR). Los documentos se actualizan utilizando la sentencia SQL UPDATE. Descomposición de esquemas XML anotados Los datos de los documentos XML pueden descomponerse o almacenarse en columnas relacionales y XML utilizando la descomposición de esquemas XML anotados. La descomposición almacena los datos en columnas de acuerdo con las anotaciones que se añaden a los documentos de esquema XML. Estas anotaciones correlacionan los datos de documentos XML con columnas de tablas. Los documentos de esquema XML referenciados por la función de descomposición se almacenan en el repositorio de esquemas XML (XSR). Registro en el repositorio de esquemas XML (XSR) El repositorio de esquemas XML (XSR) almacena esquemas XML que se utilizan para la validación o la descomposición de documentos XML. El registro de esquemas XML suele ser un requisito previo para otras tareas realizadas en documentos XML que tienen una dependencia de estos esquemas. Los esquemas XML se registran en el XSR utilizando procedimientos almacenados proporcionados por DB2.
Salida Se utiliza SQL para recuperar los datos XML del sistema de base de datos. Al consultar datos XML utilizando una fullselect de SQL, la consulta se realiza en el nivel de columna. Por esta razón, la consulta sólo puede devolver documentos XML completos. Puede utilizarse la función de tabla incorporada XMLTABLE para recuperar fragmentos de un documento XML en una consulta SQL. También están disponibles diversas funciones de publicación para construir valores XML a partir de datos relacionales almacenados en un servidor de bases de datos DB2. Los valores XML construidos con estas funciones de publicación no tienen que ser documentos XML bien formados.
Comparación entre XML y los modelos relacionales Al diseñar las bases de datos, debe decidir si los datos son más adecuados para el modelo XML o el modelo relacional. Su diseño también puede aprovechar la naturaleza de una base de datos DB2: la capacidad de dar soporte a datos tanto relacionales como XML en una única base de datos. Aunque esta descripción explica algunas de las principales diferencias entre los modelos y los factores que se aplican a cada uno, existen diversos factores que pueden determinar la opción más adecuada para su implementación. Utilice esta descripción como guía para evaluar los factores que pueden afectar a su implementación específica.
Principales diferencias entre datos XML y datos relacionales Los datos XML son jerárquicos; los datos relacionales se representan en un modelo de relaciones lógicas Un documento XML contiene información sobre la relación de los elementos de datos entre sí en forma de jerarquía. En el modelo relacional, los únicos tipos de relaciones que pueden definirse son relaciones de tabla padre y tabla dependiente. Los datos XML son autodescriptivos; los datos relacionales, no Un documento XML contiene no sólo los datos, sino también la codificación de los datos que explica lo que son. Un solo documento puede contener distintos tipos de datos. En el modelo Programación SQL XML
5
relacional, el contenido de los datos se define en su definición de columna. Todos los datos de una columna deben tener el mismo tipo de datos. Los datos XML tienen un orden inherente; los datos relacionales, no En un documento XML, se presupone que el orden en que se especifican los elementos de datos es el orden de los datos en el documento. Con frecuencia no hay ninguna otra manera de especificar el orden dentro del documento. En los datos relacionales, el orden de las filas no está garantizado a menos que se especifique una cláusula ORDER BY para una o más columnas de una fullselect.
Factores que influyen en la elección del modelo de datos El tipo de datos que debe almacenar puede ayudarle a determinar cómo almacenarlos. Por ejemplo, si los datos son naturalmente jerárquicos y autodescriptivos, puede almacenarlos como datos XML. Sin embargo, hay otros factores que pueden influir en su decisión acerca de qué modelo utilizar: Cuando se necesita la máxima flexibilidad Las tablas relacionales siguen un modelo bastante rígido. Por ejemplo, normalización de una tabla en muchas o la desnormalización de muchas tablas en una puede ser muy difícil. Si el diseño de los datos cambia a menudo, representarlos como datos XML es una mejor opción. Por ejemplo, los esquemas XML pueden evolucionar a lo largo del tiempo. Cuando se necesita el máximo rendimiento para la recuperación de datos La serialización e interpretación de datos XML están sujetas a algunos costes. Si el rendimiento es más importante que la flexibilidad, los datos relacionales podrían ser la mejor opción. Cuando los datos se procesan posteriormente como datos relacionales Si el proceso posterior de los datos depende de que los datos estén almacenados en una base de datos relacional, podría ser adecuado almacenar partes de los datos como relacionales, utilizando la descomposición. Un ejemplo de esta situación es cuando se aplica el proceso analítico en línea (OLAP) a los datos de un almacén de datos. Además, si es necesario otro proceso en el documento XML en conjunto, almacenar algunos de los datos como relacionales así como almacenar el documento XML completo podría ser un enfoque adecuado en este caso. Cuando los componentes de datos tienen un significado fuera de una jerarquía Los datos pueden ser inherentemente jerárquicos en su naturaleza, pero los componentes hijo no necesitan los padres para proporcionar valor. Por ejemplo, una orden de compra puede contener números de pieza. Las órdenes de compra con los números de pieza pueden representarse mejor como documentos XML. Sin embargo, cada número de pieza tiene asociada una descripción de pieza. Es posible que sea mejor incluir las descripciones de pieza en una tabla relacional, porque la relación entre los números de pieza y las descripciones de pieza es lógicamente independiente de las órdenes de compra en las que se utilizan los números de pieza. Cuando los atributos de datos se aplican a todos los datos, o sólo a un pequeño subconjunto de los datos Algunos conjuntos de datos tienen un gran número de atributos posibles, pero sólo un pequeño número de esos atributos se aplica a cualquier valor de datos concreto. Por ejemplo, en un catálogo de venta, hay muchos atributos de datos posibles, como por ejemplo tamaño, color, peso, material, estilo, tejido, requisitos de alimentación o requisitos de combustible. Para cualquier artículo determinado de catálogo, únicamente es relevante un subconjunto de estos atributos: los requisitos de alimentación son significativos para una sierra de mesa, pero no para un abrigo. Este tipo de datos es difícil de representar y buscar con un modelo relacional, pero relativamente fácil de representar y buscar con un modelo XML. Cuando es necesaria la integridad referencial Las columnas XML no pueden definirse como parte de restricciones referenciales. Por tanto, si los valores de documentos XML deben participar en restricciones referenciales, debe almacenar los datos como datos relacionales. Cuando los datos deben actualizarse con frecuencia Los datos XML de una columna XML sólo se actualizan sustituyendo documentos completos. Si
6
IBM i: Programación SQL XML
tiene que actualizar frecuentemente pequeños fragmentos de documentos muy grandes para un gran número de filas, puede ser más eficaz de almacenar los datos en columnas que no sean XML. Sin embargo, si está actualizando documentos pequeñas y sólo unos pocos documentos a la vez, almacenarlos como XML también puede ser eficaz.
Guía de aprendizaje de XML El tipo de datos XML permite definir columnas de tabla que almacenen en cada fila un único documento XML bien formado. Esta guía de aprendizaje muestra cómo configurar una base de datos DB2 para almacenar datos XML y realizar operaciones básicas con las funciones XML. Una vez haya completada esta guía de aprendizaje, sabrá realizar las tareas siguientes: v Crear una tabla que puede almacenar datos XML v Insertar documentos XML en columnas de tipo XML v Actualizar documentos XML almacenados en una columna XML v Validar documentos XML contra esquemas XML v Transformar con hojas de estilo XSLT
Preparación Los ejemplos de los ejercicios deben especificarse o copiarse y pegarse en la herramienta de ejecución de scripts SQL de IBM i Navigator. El SQL interactivo no mostrará los datos de resultado XML como datos serializados.
Ejercicio 1: Crear una tabla que puede almacenar datos XML Este ejercicio muestra cómo se crea una tabla que contiene una columna XML. Cree una tabla llamada Customer que contenga una columna XML: CREATE SCHEMA POSAMPLE; SET CURRENT SCHEMA POSAMPLE; CREATE TABLE Customer (Cid BIGINT NOT NULL PRIMARY KEY, Info XML);
Tenga en cuenta que la especificación de una clave primaria es opcional y no es necesaria para almacenar XML. También puede añadir una o más columnas XML a tablas existentes con la sentencia SQL ALTER TABLE. Volver a la guía de aprendizaje
Ejercicio 2: Insertar documentos XML en columnas de tipo XML Los documentos XML bien formados se insertan en columnas de tipo XML utilizando la sentencia SQL INSERT. Este ejercicio muestra cómo insertar documentos XML en columnas XML. Normalmente, los documentos XML se insertan utilizando programas de aplicación. Aunque se pueden insertar datos XML mediante aplicaciones utilizando tipos XML, binarios o de carácter, es aconsejable utilizar tipos XML o binarios si se procesan documentos XML de muchos orígenes con distintas codificaciones. Este ejercicio muestra cómo insertar manualmente documentos XML en columnas de tipo XML en la ejecución de scripts SQL, donde el documento XML siempre es un literal de caracteres. En la mayoría de los casos, los datos de serie no pueden asignarse directamente a un destino con un tipo de datos XML; los datos deben analizarse primero explícitamente utilizando la función XMLPARSE. Sin embargo, en operaciones INSERT o UPDATE, los datos de serie pueden asignarse directamente a columnas XML sin
Programación SQL XML
7
llamar explícitamente a la función XMLPARSE. En estos dos casos, los datos de serie se analizan implícitamente. Consulte la documentación de análisis de XML para obtener más información. Inserte tres documentos XML en la tabla Customer que ha creado en el Ejercicio 1: INSERT INTO Customer (Cid, Info) VALUES (1000, ’ Kathy Smith 5 Rosewood Toronto Ontario M6W 1E6 416-555-1358 ’); INSERT INTO Customer (Cid, Info) VALUES (1002, ’ Jim Noodle 25 EastCreek Markham Ontario N9C 3T6 905-555-7258 ’); INSERT INTO Customer (Cid, Info) VALUES (1003, ’ Robert Shoemaker 1596 Baseline Aurora Ontario N8X 7F8 905-555-2937 ’);
Puede confirmar que los registros se han insertado satisfactoriamente como se indica a continuación: SELECT * from Customer;
Si está ejecutando este ejercicio en SQL interactivo, los valores XML no se serializarán automáticamente. Debe utilizar explícitamente la función XMLSERIALIZE para ver los datos insertados. Volver a la guía de aprendizaje
Ejercicio 3: Actualizar documentos XML almacenados en una columna XML Este ejercicio muestra cómo actualizar documentos XML con sentencias SQL.
Actualización con SQL Para actualizar un documento XML almacenado en una columna XML mediante SQL, debe realizar una actualización de documento completo utilizando la sentencia UPDATE de SQL. Actualice uno de los documentos insertados en el Ejercicio 2 del siguiente modo (donde ha cambiado los valores de los elementos , y ): UPDATE customer SET info = ’ Jim Noodle
8
IBM i: Programación SQL XML
1150 Maple Drive Newtown Ontario Z9Z 2P2 905-555-7258 ’ WHERE Cid = 1002;
Puede confirmar que el documento XML se ha actualizado como se indica a continuación: SELECT * from Customer;
Si está ejecutando este ejercicio en SQL interactivo, los valores XML no se serializarán automáticamente. Debe utilizar explícitamente la función XMLSERIALIZE para ver los datos actualizados. La fila WHERE Cid="1002" contiene los valores , y cambiados. Los documentos XML pueden identificarse por los valores de las columnas no XML de la misma tabla. Volver a la guía de aprendizaje
Ejercicio 4: Validar documentos XML con respecto a esquemas XML Este ejercicio muestra cómo validar documentos XML. Sólo puede validar documentos XML con respecto a esquemas XML; la validación de DTD no está soportada. (Aunque no puede validar con respecto a DTD, puede insertar documentos que contengan un DOCTYPE o que hagan referencia a DTD.) Existen herramientas disponibles, como las de IBM Rational Application Developer, que ayudan a generar esquemas XML a partir de diversos orígenes, incluyendo DTD, tablas existentes o documentos XML. Antes de poder validar, debe registrar el esquema XML en el repositorio de esquemas XML incorporado (XSR). Este proceso implica registrar cada documento de esquema XML que forma el esquema XML. Una vez registrados correctamente todos los documentos de esquema XML, debe completar el registro. Registre y complete el registro del esquema XML posample.customer como se indica a continuación: CREATE PROCEDURE SAMPLE_REGISTER LANGUAGE SQL BEGIN DECLARE CONTENT BLOB(1M); VALUES BLOB(’ Programación SQL XML
9
’) INTO CONTENT; CALL SYSPROC.XSR_REGISTER(’POSAMPLE’, ’CUSTOMER’, ’http://posample.org’, CONTENT, null); END; SET PATH POSAMPLE; CALL SAMPLE_REGISTER; CALL SYSPROC.XSR_COMPLETE(’POSAMPLE’, ’CUSTOMER’, null, 0);
Puede verificar que el esquema XML se ha registrado satisfactoriamente consultando la vista de catálogo QSYS2.XSROBJECTS, que contiene información sobre los objetos almacenados en el XSR. Esta consulta y su resultado (formateado para mayor claridad) son los siguientes: SELECT XSROBJECTSCHEMA, XSROBJECTNAME FROM QSYS2.XSROBJECTS WHERE XSROBJECTSCHEMA = ’POSAMPLE’; XSROBJECTSCHEMA -------------------POSAMPLE
XSROBJECTNAME -------------------CUSTOMER
Este esquema XML ahora está disponible para ser utilizado para la validación. La validación se realiza normalmente durante una operación INSERT o UPDATE. Realice la validación utilizando la función XMLVALIDATE. La operación INSERT o UPDATE en la que se ha especificado XMLVALIDATE sólo se realizará si la validación es satisfactoria. La sentencia INSERT siguiente inserta un nuevo documento XML en la columna Info de la tabla Customer, sólo si el documento es válido según el esquema XML posample.customer registrado anteriormente. INSERT INTO Customer(Cid, Info) VALUES (1004, XMLVALIDATE (XMLPARSE (DOCUMENT ’ Robert Shoemaker 1596 Baseline Aurora Ontario N8X 7F8 905-555-7258 416-555-2937
10
IBM i: Programación SQL XML
905-555-8743 613-555-3278 ’ PRESERVE WHITESPACE ) ACCORDING TO XMLSCHEMA ID posample.customer ));
XMLVALIDATE opera sobre datos XML. Debido a que el documento XML de este ejemplo se pasa como datos de tipo carácter, XMLVALIDATE debe utilizarse junto con la función XMLPARSE. Tenga en cuenta que los datos de tipo carácter pueden asignarse directamente a XML sólo en sentencias INSERT, UPDATE o MERGE. Aquí se utiliza una sentencia INSERT. La función XMLPARSE analiza su argumento como un documento XML y devuelve un valor XML. Para verificar que la validación y la inserción han sido satisfactorias, consulte la columna Info: SELECT Info FROM Customer;
Esta consulta debe devolver tres documentos XML, uno de los cuales es el documento que acaba de insertar. Volver a la guía de aprendizaje
Ejercicio 5: Transformación con hojas de estilo XSLT Puede utilizar la función XSLTRANSFORM para convertir los datos XML de la base de datos a otros formatos. Este ejemplo muestra cómo utilizar la función incorporada XSLTRANSFORM para transformar documentos XML que están almacenados en la base de datos. En este caso, el documento XML contiene un número arbitrario de registros de estudiantes universitarios. Cada elemento student contiene el ID, el nombre, el apellido, la edad del estudiante y la universidad a la que asiste, como se indica a continuación:
La finalidad de esta transformación XSLT es extraer la información de los registros XML y crear una página web HTML que pueda visualizarse en un navegador. Con este objetivo, utilizaremos la siguiente hoja de estilo XSLT, que también está almacenada en la base de datos.
| StudentID | First Name | Last Name | Age | University |
Programación SQL XML
11
| | | | |
Esta hoja de estilo funcionará tanto con una transformación XSLT estándar como utilizando un archivo de parámetros suministrado para controlar su comportamiento en tiempo de ejecución. 1. Cree la tabla en la que puede almacenar el documento XML y el documento de hoja de estilo. SET CURRENT SCHEMA USER; CREATE TABLE XML_TAB (DOCID INTEGER, XML_DOC XML, XSL_DOC CLOB(1M));
2. Inserte los documentos en las tablas. En este ejemplo, el documento XML y la hoja de estilo XSLT puede cargarse en la misma tabla como valores de columna distintos. La sentencia INSERT utiliza una versión truncada de la hoja de estilo XSLT como tercer valor. Para utilizar la siguiente sentencia INSERT, sustituya el valor de hoja de estilo truncada por la hoja de estilo XSLT indicada anteriormente en este ejercicio. INSERT INTO XML_TAB VALUES (1, ’ ’, ’ ’) ;
La siguiente sentencia SELECT convierte el documento XML de muestra utilizando la hoja de estilo XSLT. SELECT XSLTRANSFORM (XMLDOC USING XSLT ) FROM XMLDATA, XMLTRANS where ID = 1 and XSLID = 1
El mandato XSLTRANSFORM convierte el documento XML utilizando la primera hoja de estilo XSLT y devuelve el XML siguiente con toda la información de espacio de nombres eliminada. Matt Foreman 1596 Baseline Toronto Ontario M3Z 5H9 905-555-4789 416-555-3376 Gopher Runner
26
IBM i: Programación SQL XML
416-555-3426
Ejemplo de hoja de estilo XSLT que conserva el enlace de espacio de nombres para un elemento En el ejemplo siguiente se utiliza una hoja de estilo XSLT que conserva el enlace de espacio de nombres sólo para los elementos phone. El nombre del elemento se especifica en la variable XSLT mynode. El ejemplo almacena la hoja de estilo en la tabla XMLTRANS y utiliza una sentencia SELECT para aplicar la hoja de estilo al documento XML. Añada la hoja de estilo a la tabla XMLTRANS utilizando la siguiente sentencia INSERT. insert into XMLTRANS (XSLID, XSLT) values ( 2, ’ phone ’);
La siguiente sentencia SELECT convierte el documento XML de muestra utilizando la segunda hoja de estilo XSLT porque se especifica XSLID = 2.
Programación SQL XML
27
SELECT XSLTRANSFORM (XMLDOC USING XSLT) FROM XMLDATA, XMLTRANS where ID = 1 and XSLID = 2 ;
El mandato XSLTRANSFORM convierte el documento XML utilizando la segunda hoja de estilo XSLT y devuelve el XML siguiente únicamente con los espacios de nombres de los elementos phone. Matt Foreman 1596 Baseline Toronto Ontario M3Z 5H9 905-555-4789 416-555-3376 Gopher Runner 416-555-3426
Consideraciones importantes para la transformación de documentos XML Al utilizar la función incorporada XSLTRANSFORM para convertir documentos XML, debe tener en cuenta algunas consideraciones y restricciones importantes. Tenga en cuenta lo siguiente al transformar documentos XML: v Los documentos XML de origen deben tener una única raíz y estar bien formados. v Dado que la transformación XSLT genera caracteres UTF-8 de forma predeterminada, la corriente de salida puede perder caracteres si se inserta en una columna de carácter que no es Unicode.
Restricciones v Sólo se da soporte a la recomendación W3C XSLT Versión 1.10. v Todos los parámetros y el tipo de resultado deben ser tipos SQL; no pueden ser nombres de archivo. v La transformación con más de un documento de hoja de estilo (utilizando una declaración xsl:include) no está soportada.
Manejo de caracteres especiales en funciones de publicación de SQL/XML Las funciones de publicación de SQL/XML tienen un comportamiento predeterminado para el manejo de caracteres especiales.
Valores SQL para valores XML Determinados caracteres se consideran caracteres especiales dentro de documentos XML, y deben aparecer en su formato de escape utilizando su representación de entidad. A continuación se indican estos caracteres especiales: Tabla 1. Caracteres especiales y sus representaciones de entidad Carácter especial
Representación de entidad
<
<
28
IBM i: Programación SQL XML
Tabla 1. Caracteres especiales y sus representaciones de entidad (continuación) Carácter especial
Representación de entidad
>
>
&
&
"
"
Al publicar valores SQL como valores XML utilizando las funciones de publicación de SQL/XML, estos caracteres especiales se especifican con escape y se sustituyen por sus entidades predefinidas.
Identificadores SQL y QNames Al publicar o construir valores XML a partir de valores SQL, puede ser necesario correlacionar un identificador de SQL con un nombre calificado XML, o QName. Sin embargo, el conjunto de caracteres que se permiten en identificadores SQL delimitados difiere de los permitidos en un QName. Esta diferencia implica que algunos caracteres utilizados en los identificadores de SQL no serán válidos en QNames. Por lo tanto, estos caracteres se sustituyen por su representación de entidad en el QName. Por ejemplo, considere el identificador de SQL delimitado "phone@work". Debido a que el carácter @ no es un carácter válido en un QName, el carácter se escapa y el QName se convierte en: phone@work. Tenga en cuenta que este comportamiento de escape predeterminado se aplica sólo a los nombres de columna. Para los identificadores de SQL que se proporcionan como nombre de elemento en XMLELEMENT o como nombre en la cláusula AS de XMLFOREST y XMLATTRIBUTES, no hay ningún valor predeterminado de escape. En estos casos debe especificar QNames válidos. Consulte las especificaciones de espacio de nombres XML de W3C para obtener más detalles sobre los nombres válidos.
Serialización de XML La serialización de XML es el proceso de convertir datos XML del formato que tienen en una base de datos DB2 al formato de serie serializada que tienen en la aplicación. Puede dejar que el gestor de bases de datos DB2 realice implícitamente la serialización o invocar la función XMLSERIALIZE para solicitar explícitamente la serialización de XML. El uso más común de la serialización XML es al enviar los datos XML desde el servidor de bases de datos al cliente. La serialización implícita es el método preferido en la mayoría de los casos porque su codificación es más sencilla, y el envío de datos XML al cliente permite que el cliente de DB2 maneje los datos XML correctamente. La serialización explícita requiere un manejo adicional, descrito más adelante, que el cliente maneja automáticamente durante serialización implícita. En general, la serialización implícita es preferible porque es más eficaz enviar datos al cliente como datos XML. Sin embargo, en determinadas circunstancias (que se describen más adelante), es preferible ejecutar XMLSERIALIZE de forma explícita. El mejor tipo de datos al que convertir los datos XML es el tipo de datos BLOB, debido a que la recuperación de datos binarios da como resultado menos problemas de codificación.
Serialización de XML implícita Con la serialización implícita para aplicaciones DB2 CLI y de SQL incorporado, el servidor de bases de datos DB2 añade a los datos una declaración XML con la codificación adecuada especificada. En las aplicaciones .NET, el servidor de bases de datos DB2 también añade una declaración XML. En las aplicaciones Java, en función de los métodos de objeto SQLXML a los que se llame para recuperar los Programación SQL XML
29
datos del objeto SQLXML, los datos con una declaración XML añadida por el servidor de bases de datos DB2 no se devolverán. Ejemplo: en un programa C, serializar implícitamente el documento customerinfo para el ID de cliente '1000' y recuperar el documento serializado en una variable del lenguaje principal XML binaria. Los datos recuperados se encuentran en el esquema de codificación UTF-8 y contienen una declaración XML. EXEC SQL BEGIN DECLARE SECTION; SQL TYPE IS XML AS BLOB (1M) xmlCustInfo; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT INFO INTO :xmlCustInfo FROM Customer WHERE Cid=1000;
Serialización de XML explícita Después de una invocación de XMLSERIALIZE explícita, los datos tienen un tipo no XML en el servidor de bases de datos, y se envían al cliente como ese tipo de datos. La función escalar XMLSERIALIZE permite especificar: v El tipo de datos SQL al que se convierten los datos cuando se serializan. El tipo de datos es de carácter, gráfico o binarios. v Si los datos de salida deben incluir la especificación de codificación explícita (EXCLUDING XMLDECLARATION o INCLUDING XMLDECLARATION). La salida de XMLSERIALIZE son datos Unicode, de carácter o gráficos. Si recupera los datos serializados en un tipo de datos no binarios, los datos se convierten a la codificación de la aplicación, pero la especificación de codificación no se modifica. Por tanto, probablemente la codificación de los datos no se ajustará a la especificación de codificación. Esta situación genera datos XML que no pueden ser analizados por los procesos de aplicación que se basan en el nombre de la codificación. En general, la serialización implícita es preferible porque es más eficaz enviar datos al cliente como datos XML. Sin embargo, cuando el cliente no admite datos XML, es preferible realizar una XMLSERIALIZE explícita: Si el cliente es de una versión anterior que no admite el tipo de datos XML y se utiliza la serialización de XML implícita, el servidor de bases de datos DB2 convierte los datos a un CLOB o DBCLOB antes de enviarlos al cliente. Si desea que los datos recuperados sean de algún otro tipo, puede utilizar XMLSERIALIZE. Ejemplo: la columna XML Info de la tabla de ejemplo Customer contiene un documento que contiene el equivalente jerárquico de los datos siguientes: Kathy Smith 5 Rosewood Toronto Ontario M6W 1E6 416-555-1358
30
IBM i: Programación SQL XML
Invoque XMLSERIALIZE para serializar los datos y convertirlos a un tipo BLOB antes de recuperarlos en una variable del lenguaje principal. SELECT XMLSERIALIZE(Info as BLOB(1M)) into :hostvar from Customer WHERE CID=1000
Diferencias en un documento XML tras el almacenamiento y recuperación Al almacenar un documento XML en una base de datos DB2 y luego recuperar esa copia de la base de datos, es posible que el documento recuperado no sea exactamente igual que el documento original. Este comportamiento está definido por el estándar XML y SQL/XML. Algunos de los cambios en el documento se producen cuando se almacena el documento. Dichos cambios son: v Si ejecuta XMLVALIDATE, el servidor de bases de datos: – Elimina los espacios en blanco descartables del documento de entrada v Si no solicita la validación de XML, el servidor de bases de datos: – Elimina los espacios en blanco de límite, si no solicita que se conserven – Sustituye todos los pares de retorno de carro y salto de línea (U+000D y U+000A) o retornos de carro (U+000D) del documento por saltos de línea (U+000A) – Realiza la normalización de valores de atributo, según la especificación XML 1.0 Este proceso provoca la sustitución de los caracteres de salto de línea (U+000A) de los atributos por caracteres de espacio (U+0020). Se producen cambios adicionales cuando se recuperan los datos de una columna XML. Dichos cambios son: v Si los datos tienen una declaración XML antes de enviarlos al servidor de bases de datos, la declaración XML no se conserva. Con la serialización implícita para aplicaciones DB2 CLI y de SQL incorporado, el servidor de bases de datos DB2 añade a los datos una declaración XML con la codificación adecuada especificada. En las aplicaciones .NET, el servidor de bases de datos DB2 también añade una declaración XML. En las aplicaciones Java, en función de los métodos de objeto SQLXML a los que se llame para recuperar los datos del objeto SQLXML, los datos con una declaración XML añadida por el servidor de bases de datos DB2 no se devolverán. Si ejecuta la función XMLSERIALIZE, el servidor de bases de datos DB2 añade una declaración XML con una especificación de la codificación si se especifica la opción INCLUDING XMLDECLARATION. v En el contenido de un documento o en los valores de atributo, algunos caracteres se sustituyen por sus entidades XML predefinidas. Dichos caracteres y sus entidades predefinidas son los siguientes: Carácter
Valor Unicode
Representación de entidad
AMPERSAND
U+0026
&
SIGNO MENOR QUE
U+003C
<
SIGNO MAYOR QUE
U+003E
>
v Dentro de los valores de atributo, el carácter de COMILLAS (U+0022) se sustituye por su entidad XML predefinida ". v Si el documento de entrada tiene una declaración de DTD, la declaración no se conserva y no se generan códigos basados en la DTD. v Si el documento de entrada contiene secciones CDATA, esas secciones no se conservan en la salida.
Tipos de datos para el archivado de documentos XML Aunque puede almacenar datos de serie serializada XML en una columna de cualquier tipo de carácter o binario, las columnas no XML deben utilizarse sólo para el archivado de datos XML. El mejor tipo de datos de columna para el archivado de datos XML es un tipo de datos binarios, como por ejemplo BLOB. Programación SQL XML
31
El uso de una columna de tipo carácter para el archivado introduce conversiones de CCSID, que pueden hacer que un documento sea incoherente con su formato original.
Utilización de XMLTABLE para hacer referencia al contenido XML como una tabla relacional La función de tabla incorporada XMLTABLE puede utilizarse para recuperar el contenido de un documento XML como un conjunto de resultados al que puede hacerse referencia en SQL. Supongamos que tiene una tabla denominada EMP con una columna XML definida del siguiente modo: CREATE TABLE EMP (DOC XML)
La tabla contiene 2 filas, que tienen este aspecto: John Doe 344 55000 Peter Pan 216 905-416-5004 Mary Jones 415 905-403-6112 647-504-4546 64000
En la invocación de la función XMLTABLE, especifique una expresión XPath de generación de filas y, en la cláusula columns, una o varias expresiones de generación de columnas. En este ejemplo, la expresión de generación de filas es la expresión XPath $d/dept/employee. La cláusula passing indica que la variable $d hace referencia a la columna XML doc de la tabla emp. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING COLUMNS empID INTEGER firstname VARCHAR(20) lastname VARCHAR(25)
emp.doc AS "d" PATH ’@id’, PATH ’name/first’, PATH ’name/last’) AS X
La expresión de generación de filas se aplica a cada documento XML de la columna XML y produce uno o varios elementos employee (subárboles) por documento. La salida de la función XMLTABLE contiene una fila para cada elemento employee. Por tanto, la salida producida por la expresión XPath de generación de filas determina la cardinalidad del conjunto de resultados de la sentencia SELECT.
32
IBM i: Programación SQL XML
La cláusula COLUMNS se utiliza para transformar datos XML en datos relacionales. Cada una de las entradas de esta cláusula define una columna con un nombre de columna y un tipo de datos SQL. En el ejemplo anterior, las filas devueltas tienen 3 columnas denominadas empID, firstname y lastname cuyos tipos de datos son Integer, Varchar(20) y Varchar(25), respectivamente. Los valores de cada columna se extraen de los elementos employee, producidos por la expresión XPath de generación de filas, y se convierten a los tipos de datos SQL. Por ejemplo, la vía de acceso name/first se aplica a cada elemento employee para obtener el valor de la columna firstname. La expresión de generación de filas proporciona el contexto para las expresiones de generación de columnas. En otras palabras, normalmente puede añadir una expresión de generación de columnas a la expresión de generación de filas para hacerse una idea de lo que una función XMLTABLE determinada devuelve para una columna. El resultado de la consulta anterior es: EMPID ----------901 902 903
FIRSTNAME -------------------John Peter Mary
LASTNAME ------------------------Doe Pan Jones
Tenga en cuenta que las expresiones de vía de acceso de la cláusula COLUMNS no deben devolver más de un elemento por fila. Si una expresión de vía de acceso devuelve una secuencia de dos o más elementos, la ejecución de XMLTABLE normalmente fallará, ya que no es posible convertir una secuencia de valores XML a un único valor SQL atómico.
Ejemplo: Utilizar XMLTABLE para manejar elementos que faltan El código XML puede contener elementos opcionales que no están presentes en todos los documentos Por ejemplo, el empleado Peter Pan no tiene un elemento de salario (salary), ya no es un campo de datos obligatorio. Esto es fácil de tratar debido a que la función XMLTABLE genera valores NULL para los elementos que faltan. Puede escribir consultas XMLTABLE como si el elemento salary siempre estuviera presente. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING COLUMNS empID INTEGER firstname VARCHAR(20) lastname VARCHAR(25) salary INTEGER
doc AS "d" PATH PATH PATH PATH
’@id’, ’name/first’, ’name/last’, ’salary’) AS X
Esta consulta devuelve el resultado siguiente. Observe que la columna salary de Peter Pan tiene el valor NULL porque el documento XML no contiene ningún valor salarial. EMPID ----------901 902 903
FIRSTNAME -------------------John Peter Mary
LASTNAME ------------------------Doe Pan Jones
SALARY ---------55000 64000
Si desea que aparezca un valor distinto de NULL para un elemento que falta, puede definir un valor predeterminado que se utilizará cuando falte el elemento esperado. A continuación, definimos la columna de resultados de salario para que devuelva 0 en lugar de NULL. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING doc AS "d" COLUMNS empID INTEGER PATH ’@id’, firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’, salary INTEGER DEFAULT 0 PATH ’salary’) AS X
Programación SQL XML
33
Ejemplo: Utilizar XMLTABLE para crear un subconjunto de datos de resultado A menudo se desea producir un resultado que contenga un subconjunto de las filas posibles basándose en algún predicado de filtrado. Hay varias maneras de producir un subconjunto de filas. Una solución es añadir una cláusula WHERE a la consulta que debe filtrarse utilizando una columna de salida. Esto requiere generar todas las filas sólo para descartarlas inmediatamente. Otra solución es utilizar predicados de filtro en la expresión de generación de filas de la función XMLTABLE. Supongamos que necesita generar filas sólo para los empleados del edificio 114. Puede añadir una condición correspondiente a XMLTABLE como la siguiente: SELECT X.* FROM emp, XMLTABLE (’$d/dept[@bldg="114"]/employee’ PASSING doc AS "d" COLUMNS empID INTEGER PATH ’@id’, firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’, salary INTEGER DEFAULT 0 PATH ’salary’) AS X
Esta consulta devuelve una sola fila para Mary Jones, que es el único empleado del edificio 114.
Ejemplo: Utilizar XMLTABLE para manejar varios valores A veces una expresión de vía de acceso hace referencia a un elemento que tiene varios valores. Las expresiones de vía de acceso de la cláusula COLUMNS no deben generar más de un elemento por fila. En los documentos de muestra, observe que el empleado Mary Jones tiene dos números de teléfono. Si necesita consultar estos datos y devolver una tabla relacional con el nombre y número de teléfono de cada empleado, la consulta que escribirá puede ser la siguiente: SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING doc AS "d" COLUMNS firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’, phone VARCHAR(12) PATH ’phone’) AS X
Cuando se ejecuta con los documentos de muestra, esta consulta falla porque hay dos valores para phone. Es necesaria otra solución. Devolver sólo el primer valor Una forma de tratar este problema es devolver sólo uno de los diversos números de teléfono. Si necesita información resumida de cada empleado, un solo número de teléfono puede ser suficiente. La devolución de una única aparición del elemento phone puede obtenerse con un predicado posicional en la expresión XPath para la columna phone. En XPath se utilizan corchetes para especificar predicados. Para obtener el primer elemento phone de un empleado, utilice un predicado posicional, escrito como [1] o [fn:position()=1]. La primera anotación, [1], es una versión abreviada de la segunda. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING doc AS "d" COLUMNS firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’, phone VARCHAR(12) PATH ’phone[1]’) AS X
Devolver varios valores como XML
34
IBM i: Programación SQL XML
Otra opción para devolver varios números de teléfono para un solo empleado es devolver una secuencia XML de elementos phone. Para lograrlo, la columna phone generada debe ser de tipo XML, lo cual permite devolver un valor XML como resultado de la expresión XPath. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING COLUMNS firstname VARCHAR(20) lastname VARCHAR(25) phone XML
doc AS "d" PATH ’name/first’, PATH ’name/last’, PATH ’phone’) AS X
El resultado de esta consulta es: FIRSTNAME ----------John Peter Mary
LASTNAME ---------Doe Pan Jones
PHONE -----------------905-416-5004 905-403-6112647-504-4546
El valor XML devuelto en la columna phone para Mary Jones no es un documento XML bien formado, ya que no hay ningún elemento raíz único. DB2 puede procesar este valor, pero el usuario no podrá insertarlo en una columna XML ni analizarlo con un analizador XML. La combinación de varios números de teléfono en un único valor VARCHAR o XML puede requerir código adicional en la aplicación para utilizar los números individuales. Devolver varias columnas Otra solución es devolver a cada número de teléfono como un valor VARCHAR separado generando un número fijo de columnas phone de resultado. Este ejemplo utiliza predicados posicionales para devolver números de teléfono en dos columnas. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING COLUMNS firstname VARCHAR(20) lastname VARCHAR(25) phone VARCHAR(12) phone2 VARCHAR(12)
doc AS "d" PATH PATH PATH PATH
’name/first’, ’name/last’, ’phone[1]’, ’phone[2]’) AS X
Un inconveniente obvio para este enfoque es que un número variable de elementos se correlaciona con un número fijo de columnas. Un empleado puede tener más números de teléfono de lo esperado. Otros pueden tener menos, lo que da como resultado valores nulos. Si cada empleado tiene exactamente un teléfono fijo y un teléfono móvil, puede ser muy útil generar dos columnas con los nombres correspondientes. Devolver una fila para cada valor En lugar de devolver los números de teléfono en columnas separadas, también puede utilizar XMLTABLE para devolverlos en filas separadas. En este caso, debe devolver una fila para cada número de teléfono en lugar de una fila para cada empleado. Esto puede dar como resultado información repetida en las columnas de nombre y apellido. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee/phone’ PASSING COLUMNS firstname VARCHAR(20) PATH lastname VARCHAR(25) PATH phone VARCHAR(12) PATH
doc AS "d" ’../name/first’, ’../name/last’, ’.’) AS X
El resultado de esta consulta es: Programación SQL XML
35
FIRSTNAME ----------Peter Mary Mary
LASTNAME ---------Pan Jones Jones
PHONE -----------------905-416-5004 905-403-6112 647-504-4546
En este resultado, no hay ninguna fila para John Doe, ya que no tiene número de teléfono. Manejo de valores de vía de acceso inexistentes El ejemplo anterior no devolvía una fila para el empleado John Doe porque la expresión row-xquery se repite en todos los elementos phone y no hay ningún elemento phone para el empleado John Doe. Como resultado, el elemento employee para John Doe nunca se procesa. Para resolver este problema, debe utilizar una SQL UNION de dos funciones XMLTABLE. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee/phone’ PASSING doc AS "d" COLUMNS firstname VARCHAR(20) PATH ’../name/first’, lastname VARCHAR(25) PATH ’../name/last’, phone VARCHAR(12) PATH ’.’) AS X UNION SELECT Y.*, CAST(NULL AS VARCHAR(12)) FROM emp, XMLTABLE (’$d/dept/employee[fn:not(phone)]’ PASSING doc AS "d" COLUMNS firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’) AS Y
La expresión de la fila $d/dept/employee[fn:not(phone)] de la segunda XMLTABLE devuelve todos los empleados sin número de teléfono, añadiendo las filas de empleado que se han omitido en la primera XMLTABLE.
Ejemplo: Utilizar XMLTABLE con espacios de nombres Los espacios de nombres XML son un estándar XML de W3C para proporcionar elementos y atributos denominados de forma exclusiva en un documento XML. Los documentos XML pueden contener elementos y atributos de vocabularios distintos pero que tienen el mismo nombre. Al dar un espacio de nombres a cada vocabulario, se resuelve la ambigüedad entre nombres de atributo o elemento idénticos. En los documentos XML, los espacios de nombres XML se declaran con el atributo reservado xmlns, cuyo valor debe contener un identificador universal de recursos (URI). Los URI se utilizan como identificadores; suelen ser como un URL, pero no tienen que apuntar a una página web existente. Una declaración de espacio de nombres también puede contener un prefijo, utilizado para identificar los elementos y atributos. A continuación se muestra un ejemplo de una declaración de espacio de nombres con y sin prefijo: xmlns:ibm = "http://www.ibm.com/xmltable/" xmlns = "http://www.ibm.com/xmltable/"
Para mostrar el uso de espacios de nombres con XMLTABLE, añadimos un documento de ejemplo al ejemplo anterior, por lo que estaremos trabajando con las tres filas siguientes: John Doe 344 55000
36
IBM i: Programación SQL XML
Peter Pan 216 905-416-5004 Mary Jones 415 905-403-6112 647-504-4546 64000 James Bond 007 905-007-1007 77007
Para devolver todos los empleados de la base de datos, puede utilizar el carácter comodín * para el prefijo de espacio de nombres en las expresiones de vía de acceso. Esto hace que se tengan en cuenta todos los elementos, independientemente de los espacios de nombres, ya que este comodín (*) coincide con cualquier espacio de nombres (incluido ningún espacio de nombres). SELECT X.* FROM emp, XMLTABLE (’$d/*:dept/*:employee’ PASSING doc AS "d" COLUMNS empID INTEGER PATH ’@*:id’, firstname VARCHAR(20) PATH ’*:name/*:first’, lastname VARCHAR(25) PATH ’*:name/*:last’) AS X
El resultado de la consulta es: EMPID ----------901 902 903 144
FIRSTNAME -------------------John Peter Mary James
LASTNAME ------------------------Doe Pan Jones Bond
Para estos datos específicos, el comodín de espacio de nombres para el atributo @id no era estrictamente necesario. La razón es que el atributo @id del empleado James Bond no tiene ningún espacio de nombres. Los atributos nunca heredan los espacios de nombres de su elemento ni tampoco adoptan el espacio de nombres predeterminado. Por tanto, a menos que el nombre de atributo tenga un prefijo, no pertenece a ningún espacio de nombres. El uso de la expresión comodín es la forma más sencilla de devolver todos los empleados, independientemente del espacio de nombres.
Programación SQL XML
37
Declarar un espacio de nombres de elemento predeterminado Cuando todos los elementos que desea consultar pertenecen al mismo espacio de nombres, declarar un espacio de nombres de elemento predeterminado puede ser el modo más sencillo de escribir las consultas. Sólo necesita declarar el espacio de nombres predeterminado al principio de la expresión XPath para que todos los elementos no calificados a los que haga referencia queden asociados a dicho espacio de nombres. SELECT X.* FROM emp, XMLTABLE (’declare default element namespace "http://www.ibm.com/xmltable"; $d/dept/employee’ PASSING doc AS "d" COLUMNS empID INTEGER PATH ’@id’, firstname VARCHAR(20) PATH ’declare default element namespace "http://www.ibm.com/xmltable"; name/first’, lastname VARCHAR(25) PATH ’declare default element namespace "http://www.ibm.com/xmltable"; name/last’) AS X
El resultado es: EMPID FIRSTNAME LASTNAME ----------- -------------------- ------------------------144 James Bond
Las expresiones de generación de columnas no heredan la declaración de espacio de nombres de la expresión de generación de filas. Cada expresión de generación de columnas es una consulta XPath independiente y necesita su propia declaración de espacio de nombres. Estas declaraciones de espacios de nombres pueden ser distintas entre sí, por ejemplo, si el documento contiene varios espacios de nombres. A menudo sólo hay un espacio de nombres, en cuyo caso sería conveniente declarar un único espacio de nombres para todas las expresiones de la función XMLTABLE. Esto puede lograrse mediante la función XMLNAMESPACES(). Esta función permite declarar un espacio de nombres de elemento predeterminado y/o varios prefijos de espacio de nombres que se utilizarán dentro de la función XMLTABLE. La ventaja de utilizar la función XMLNAMESPACES es los espacios de nombres declarados son globales para todas las expresiones del contexto de XMLTABLE, por lo que todas las expresiones XPath tendrán conocimiento de estas declaraciones de espacio de nombres y no será necesario repetirlas. El espacio de nombres predeterminado declarado por la función XMLNAMESPACES se aplica tanto a la expresión de generación de filas como a todas las expresiones de generación de columnas. De este modo sólo es necesaria una declaración de espacio de nombres para todas las expresiones XPath de una función XMLTABLE. El resultado de la consulta siguiente es exactamente el mismo que en el ejemplo anterior. SELECT X.* FROM emp, XMLTABLE (XMLNAMESPACES(DEFAULT ’http://www.ibm.com/xmltable’), ’$d/dept/employee’ PASSING doc AS "d" COLUMNS empID INTEGER PATH ’@id’, firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’) AS X
Declarar un prefijo de espacio de nombre con XMLNAMESPACES Si desea seleccionar elementos y atributos de varios espacios de nombres específicos, la utilización de prefijos de espacio de nombres puede ser la mejor opción. A menos que utilice la función XMLNAMESPACES, los prefijos de espacio de nombres deben declararse para cada expresión. Sin embargo, al igual que en los espacios de nombres de elemento predeterminados, puede utilizar la función XMLNAMESPACES para evitar declaraciones de espacio de nombres repetidas. SELECT X.* FROM emp, XMLTABLE (XMLNAMESPACES(’http://www.ibm.com/xmltable’ AS "ibm"),
38
IBM i: Programación SQL XML
’$d/ibm:dept/ibm:employee’ COLUMNS empID INTEGER firstname VARCHAR(20) lastname VARCHAR(25)
PASSING doc AS "d" PATH ’@id’, PATH ’ibm:name/ibm:first’, PATH ’ibm:name/ibm:last’) AS X
Ejemplo: Numerar filas de resultados para XMLTABLE En algunos casos, puede que desee generar una columna que numere las filas generadas por XMLTABLE para un documento determinado. Esto puede ayudar a la aplicación a recordar el orden de aparición de los valores en cada documento. Para numerar las filas de resultados, utilice la cláusula FOR ORDINALITY. Tenga en cuenta que la numeración empieza por 1 para cada documento que se especifica en la función XMLTABLE. SELECT X.* FROM emp, XMLTABLE (’$d/dept/employee’ PASSING doc AS "d" COLUMNS seqno FOR ORDINALITY, empID INTEGER PATH ’@id’, firstname VARCHAR(20) PATH ’name/first’, lastname VARCHAR(25) PATH ’name/last’) AS X
El resultado de la consulta es: SEQNO EMPID -------- ----------1 901 2 902 1 903
FIRSTNAME -------------------John Peter Mary
LASTNAME ------------------------Doe Pan Jones
Actualización de datos XML Para actualizar datos de una columna XML, utilice la sentencia SQL UPDATE. Incluya una cláusula WHERE cuando desee actualizar filas específicas. Toda la columna se sustituirá. La información de entrada en la columna XML debe ser un documento XML bien formado. El tipo de datos de la aplicación puede ser XML, de carácter o binario. Al actualizar una columna XML, puede que también desee validar el documento XML de entrada contra un esquema XML registrado. Puede hacerlo con la función XMLVALIDATE. Los ejemplos siguientes muestran cómo se pueden actualizar datos XML en columnas XML. Los ejemplos utilizan la tabla MyCustomer, que es una copia de la tabla Customer de muestra. En los ejemplos se presupone que MyCustomer ya contiene una fila con un valor de ID de cliente de 1004. Se presupone que los datos XML que actualizan los datos de columna existentes se encuentran en el archivo c7.xml, cuyo contenido es el siguiente: Christine Haas 12 Topgrove Toronto Ontario N9Y-8G9 905-555-5238 416-555-2934
Ejemplo: en una aplicación JDBC, leer los datos XML del archivo c7.xml como datos binarios y utilizarlos para actualizar los datos de una columna XML:
Programación SQL XML
39
PreparedStatement updateStmt = null; String sqls = null; int cid = 1004; sqls = "UPDATE MyCustomer SET Info=? WHERE Cid=?"; updateStmt = conn.prepareStatement(sqls); updateStmt.setInt(1, cid); File file = new File("c7.xml"); updateStmt.setBinaryStream(2, new FileInputStream(file), (int)file.length()); updateStmt.executeUpdate();
Ejemplo: en una aplicación C incorporada, actualizar los datos de una columna XML a partir de una variable host XML binaria: EXEC SQL BEGIN DECLARE SECTION; sqlint64 cid; SQL TYPE IS XML AS BLOB (10K) xml_hostvar; EXEC SQL END DECLARE SECTION; ... cid=1004; /* Leer datos del archivo c7.xml en xml_hostvar */ ... EXEC SQL UPDATE MyCustomer SET Info=:xml_hostvar WHERE Cid=:cid;
En estos ejemplos, el valor del atributo Cid del elemento se almacena también en la columna relacional Cid. La cláusula WHERE de las sentencias UPDATE utiliza la columna relacional Cid para especificar las filas que deben actualizarse.
Supresión de datos XML de tablas Para suprimir filas que contienen documentos XML, utilice la sentencia SQL DELETE. Incluya una cláusula WHERE cuando desee suprimir filas específicas. Una columna XML debe ser NULL o contener un documento XML bien formado. Para suprimir un documento XML de una columna XML sin suprimir la fila, utilice la sentencia UPDATE con SET NULL para establecer la columna en NULL, si la columna está definida con admisión de nulos. El ejemplo siguiente muestra cómo pueden suprimirse datos XML de columnas XML. El ejemplo utiliza la tabla MyCustomer, que es una copia de la tabla Customer de muestra, y se presupone que MyCustomer se ha llenado con todos los datos de Customer. Ejemplo: Suprimir las filas de la tabla MyCustomer para las que el valor de la columna Cid es 1002. DELETE FROM MyCustomer WHERE Cid=1002
Repositorio de esquemas XML El repositorio de esquemas XML (XSR) es un conjunto de tablas que contienen información acerca de los esquemas XML. Los documentos de instancia XML pueden contener una referencia a un identificador universal de recursos (URI) que apunte a un esquema XML asociado. Este URI es necesario para procesar los documentos de instancia. El sistema de base de datos DB2 gestiona las de dependencias de tales artefactos XML referenciados externamente con el XSR sin necesidad de cambios en la referencia de ubicación del URI. Sin este mecanismo para almacenar los esquemas XML asociados, un recurso externo puede no ser accesible cuando la base de datos lo necesite. El XSR también elimina la sobrecarga adicional necesaria para localizar documentos externos, junto con el posible impacto sobre el rendimiento. Un esquema XML consta de un conjunto de documentos de esquema XML. Para añadir un esquema XML al XSR de DB2, debe registrar los documentos de esquema XML en DB2 llamando a los siguientes procedimientos almacenados suministrados por DB2:
40
IBM i: Programación SQL XML
SYSPROC.XSR_REGISTER Inicia el registro de un esquema XML. Debe llamar a este procedimiento almacenado al añadir el primer documento de esquema XML a un esquema XML. CALL SYSPROC.XSR_REGISTER (’user1’, ’POschema’, ’http://myPOschema/PO’, :content_host_var, NULL)
SYSPROC.XSR_ADDSCHEMADOC Añade documentos de esquema XML adicionales a un esquema XML que está en proceso de registro. Sólo puede llamar a SYSPROC.XSR_ADDSCHEMADOC para un esquema XML existente que aún no esté completo. CALL SYSPROC.XSR_ADDSCHEMADOC (’user1’, ’POschema’, ’http://myPOschema/address’, :content_host_var, NULL)
SYSPROC.XSR_COMPLETE Completa el registro de un esquema XML. CALL SYSPROC.XSR_COMPLETE (’user1’, ’POschema’, :schemaproperty_host_var, 0)
Durante la finalización del esquema XML, DB2 resuelve las referencias dentro de documentos de esquema XML a otros documentos de esquema XML. La corrección de un documento de esquema XML no se comprueban al registrar o añadir documentos. Las comprobaciones de documentos sólo se realizan cuando se completa el registro del esquema XML. Para eliminar un esquema XML del repositorio de esquemas XML de DB2, puede: v llamar al procedimiento almacenado SYSPROC.XSR_REMOVE, o v utilizar la sentencia SQL DROP XSROBJECT.
Consideraciones sobre ASP independientes para el repositorio de esquemas XML (XSR) Dado que una agrupación de almacenamiento auxiliar (ASP) independiente se puede conmutar entre varios sistemas, existen algunas consideraciones adicionales para administrar esquemas XML en una ASP. La utilización de un esquema XML debe estar restringida a la ASP independiente donde se ha registrado. No se puede hacer referencia a un esquema XML que esté definido en un grupo de ASP independientes distintas o en la ASP del sistema cuando el trabajo está conectado a la ASP independiente.
Soporte de lenguajes de programación de aplicaciones Puede escribir aplicaciones para almacenar datos XML en tablas de base de datos DB2, recuperar datos de tablas o invocar procedimientos almacenados o funciones definidas por el usuario con parámetros XML. Puede utilizar cualquiera de los lenguajes siguientes para escribir sus aplicaciones: v ILE RPG v ILE COBOL v C y C++ (SQL incorporado o CLI de DB2) v Java (JDBC o SQLJ) Un programa de aplicación puede recuperar un documento completo almacenado en una columna XML. Cuando una aplicación proporciona un valor XML a un servidor de bases de datos DB2, el servidor de bases de datos convierte los datos desde el formato de serie serializada XML a un valor XML con el CCSID especificado.
Programación SQL XML
41
Cuando una aplicación recupera datos de columnas XML, el servidor de bases de datos DB2 convierte los datos del valor XML, con el CCSID especificado, al formato de serie serializada XML. Además, es posible que el servidor de bases de datos deba convertir los datos de salida desde el CCSID XML al CCSID de la serie. Al recuperar datos XML, debe tener en cuenta el efecto de la conversión del CCSID sobre la pérdida de datos. La pérdida de datos puede producirse cuando los caracteres del CCSID XML de origen no pueden representarse en el CCSID de la serie de destino. Al extraer un documento XML, se recupera la forma serializada de un documento en una variable de aplicación.
Inserciones y actualizaciones de columnas XML en aplicaciones CLI Al actualizar o insertar datos en columnas XML de una tabla, los datos de entrada deben estar en el formato de serie serializada. Para los datos XML, se utiliza SQLBindParameter() para enlazar marcadores de parámetro a los almacenamientos intermedios de entrada. El tipo de datos XML SQL puede enlazarse a los siguientes tipos de datos de carácter y gráficos de aplicación C: v SQL_C_CHAR v SQL_VARCHAR v SQL_C_WCHAR v SQL_VARGRAPHIC Los siguientes tipos de datos LOB de carácter: v SQL_C_CLOB v SQL_C_CLOB_LOCATOR y los siguientes tipos de datos binarios: v SQL_C_BINARY v SQL_C_BLOB v SQL_C_BLOB_LOCATOR v SQL_C_BINARY Cuando se enlaza un almacenamiento intermedio de datos que contiene datos XML como un tipo de datos binarios, DB2 CLI procesa los datos XML como datos codificados internamente. Este es el método preferido porque evita la posible sobrecarga y pérdida de datos de la conversión de caracteres cuando se utilizan tipos de caracteres. Nota: Los datos XML deben estar enlazados a un tipo de datos binarios cuando el XML se recibe de muchos orígenes con diferentes esquemas de codificación. Al enlazar un almacenamiento intermedio de datos que contiene datos XML como SQL_C_CHAR o SQL_C_WCHAR, DB2 CLI procesa los datos XML como datos codificados externamente. DB2 CLI determina la codificación de los datos de la forma siguiente: v Si el tipo C es SQL_C_WCHAR, DB2 CLI presupone que los datos están codificados como UTF-16. v Si el tipo C es SQL_C_CHAR, DB2 CLI presupone que los datos están codificados en el CCSID predeterminado de un solo byte de la aplicación.
42
IBM i: Programación SQL XML
Si desea que el servidor de bases de datos analice implícitamente los datos antes de almacenarlos en una columna XML, el tipo de datos del marcador de parámetro en SQLBindParameter() debe especificarse como SQL_XML. El ejemplo siguiente muestra cómo actualizar los datos XML en una columna XML utilizando el tipo SQL_C_BINARY. char xmlBuffer[10240]; integer length; // Supongamos que una tabla llamada dept se ha creado con la sentencia siguiente: // CREATE TABLE dept (id CHAR(8), deptdoc XML) // xmlBuffer contiene un documento XML codificado internamente que debe sustituir // al documento XML existente length = strlen (xmlBuffer); SQLPrepare (hStmt, "UPDATE dept SET deptdoc = ? WHERE id = '001'", SQL_NTS); SQLBindParameter (hStmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_XML, 0, 0, xmlBuffer, 10240, &length); SQLExecute (hStmt);
Recuperación de datos XML en aplicaciones CLI Al seleccionar datos de columnas XML de una tabla, los datos de salida se encuentran en formato de serie serializada. Para los datos XML, cuando se utiliza SQLBindCol() para enlazar columnas de un conjunto de resultados de consulta con variables de aplicación, puede especificar los tipos de datos de carácter y gráficos C, los tipos de datos de LOB de carácter y gráficos y los tipos de datos binarios de la aplicación. Al recuperar un conjunto de resultados de una columna XML, debe considerar la posibilidad de enlazar la variable de aplicación a los tipos binarios. Un enlace a tipos de carácter puede provocar la pérdida de datos como resultado de la conversión del CCSID. La pérdida de datos puede producirse cuando los caracteres del CCSID XML de origen no pueden representarse en el CCSID de la serie de destino. Enlazar la variable a los tipos binarios evita estos problemas. Los datos XML se devuelven a la aplicación como datos codificados internamente. DB2 CLI determina la codificación de los datos de la forma siguiente: v Si el tipo C es SQL_C_BINARY, DB2 CLI devuelve los datos en el esquema de codificación de valor XML. v Si el tipo C es SQL_C_CHAR, DB2 CLI devuelve los datos en el esquema de codificación de caracteres de la aplicación. v Si el tipo C es SQL_C_WCHAR, DB2 CLI devuelve los datos en el esquema de codificación UTF-16. El servidor de bases de datos realiza una serialización implícita de los datos antes de devolverlos a la aplicación. Puede serializar explícitamente los datos XML a un tipo de datos específico llamando a la función XMLSERIALIZE. Sin embargo, es aconsejable realizar la serialización implícita, ya que la serialización explícita a los tipos de carácter con XMLSERIALIZE puede generar problemas de codificación. El ejemplo siguiente muestra cómo recuperar datos XML de una columna XML en una variable de aplicación binaria. char xmlBuffer[10240]; // xmlBuffer se utiliza para contener el documento XML recuperado integer length; // Supongamos que una tabla llamada dept se ha creado con la sentencia siguiente: // CREATE TABLE dept (id CHAR(8), deptdoc XML) length = sizeof (xmlBuffer); SQLExecute (hStmt, "SELECT deptdoc FROM dept WHERE id='001'", SQL_NTS); SQLBindCol (hStmt, 1, SQL_C_BINARY, xmlBuffer, &length, NULL);
Programación SQL XML
43
SQLFetch (hStmt); SQLCloseCursor (hStmt); // xmlBuffer contiene ahora un documento XML válido codificado en UTF-8
Declaración de variables del lenguaje principal XML en aplicaciones de SQL incorporado Para intercambiar datos XML entre el servidor de bases de datos y una aplicación de SQL incorporado, tiene que declarar las variables del lenguaje principal en el código fuente de la aplicación. Los datos XML se almacenan en una columna de tipo de datos XML de una tabla. Las columnas con el tipo de datos XML se describen como un SQLTYPE de columna SQL_TYP_XML, y las aplicaciones pueden enlazar varios tipos de datos específicos del lenguaje para la entrada y la salida de estas columnas o parámetros. Puede accederse directamente a las columnas XML utilizando SQL o las extensiones SQL/XML. El tipo de datos XML no se aplica únicamente a las columnas. Las funciones pueden tener argumentos de valores XML y generar también valores XML. De forma similar, los procedimientos almacenados pueden tomar valores XML como parámetros de entrada y de salida. Los datos XML son de tipo carácter por naturaleza y tienen una codificación que especifica el juego de caracteres utilizado. La codificación de los datos XML puede determinarse externamente, derivada del tipo de aplicación base que contiene la representación de serie serializada del documento XML. También puede determinarse internamente, lo cual requiere la interpretación de los datos. Para los documentos codificados en Unicode, es aconsejable utilizar una marca de orden de bytes (BOM), consistente en un código de carácter Unicode al principio de una corriente de datos. El BOM se utiliza como una signatura que define el orden de los bytes y el formato de codificación Unicode. Pueden utilizarse los tipos de carácter, gráficos y binarios existentes, que incluyen CHAR, VARCHAR, CLOB, DBCLOB y BLOB, además de variables de lenguaje principal XML para captar e insertar datos. Sin embargo, no estarán sujetos al análisis de XML implícito, como lo estarían las variables del lenguaje principal XML. En lugar de ello, se aplica una función XMLPARSE explícita con eliminación de espacios en blanco predeterminada. Para declarar variables del lenguaje principal XML en aplicaciones de SQL incorporado, en la sección de declaración de la aplicación, declare los tipos de datos AS LOB de las variables del lenguaje principal XML. Los ejemplos mostrados aquí corresponden a C, pero la sintaxis es similar para los demás lenguajes soportados. v SQL TYPE IS XML AS CLOB(n) para definir una variable de lenguaje principal CLOB que contiene datos XML codificados en el CCSID especificado por la opción de archivo QAQQINI SQL_XML_DATA_CCSID. v SQL TYPE IS XML AS DBCLOB(n) para definir una variable del lenguaje principal DBCLOB que contiene datos XML. Está codificada en el CCSID especificado por la opción de archivo QAQQINI SQL_XML_DATA_CCSID si la opción es UCS-2 o UTF-16, de lo contrario, el CCSID predeterminado es UTF-16. v SQL TYPE IS XML AS BLOB(n) para definir una variable del lenguaje principal BLOB que contiene datos XML codificados internamente. v SQL TYPE IS XML AS LOCATOR para definir un localizador que contiene datos XML. v SQL TYPE IS XML AS CLOB_FILE para definir un archivo CLOB que contiene datos XML codificados en el CCSID del archivo. v SQL TYPE IS XML AS DBCLOB_FILE para definir un archivo DBCLOB que contiene datos XML codificados en el CCSID predeterminado de doble byte de la aplicación. v SQL TYPE IS XML AS BLOB_FILE para definir un archivo BLOB que contiene datos XML codificados internamente.
44
IBM i: Programación SQL XML
Ejemplo: Cómo hacer referencia a variables host XML en aplicaciones de SQL incorporado: Las siguientes aplicaciones de ejemplo muestran cómo hacer referencia a variables host XML en C y en COBOL. Aplicación C de SQL incorporado: EXEC SQL BEGIN DECLARE; SQL TYPE IS XML AS CLOB( 10K ) xmlBuf; SQL TYPE IS XML AS BLOB( 10K ) xmlblob; SQL TYPE IS CLOB( 10K ) clobBuf; EXEC SQL END DECLARE SECTION; // utilizando una variable host XML AS CLOB // El valor XML escrito en xmlBuf irá prefijado con una declaración XML // similar a: // Nota: el nombre de codificación dependerá del valor de QAQQINI SQL_XML_DATA_CCSID EXEC SQL SELECT xmlCol INTO :xmlBuf FROM myTable WHERE id = ’001’; EXEC SQL UPDATE myTable SET xmlCol = :xmlBuf WHERE id = ’001’; // utilizando una variable host XML AS BLOB // El valor XML escrito en xmlblob irá prefijado con una declaración XML // similar a: EXEC SQL SELECT xmlCol INTO :xmlblob FROM myTable WHERE id = ’001’; EXEC SQL UPDATE myTable SET xmlCol = :xmlblob WHERE id = ’001’; // utilizando una variable host CLOB // La salida se codificará en el CCSID predeterminado de un solo byte de la aplicación, // pero no contendrá una declaración XML EXEC SQL SELECT XMLSERIALIZE (xmlCol AS CLOB(10K)) INTO :clobBuf FROM myTable WHERE id = ’001’; EXEC SQL UPDATE myTable SET xmlCol = XMLPARSE (:clobBuf PRESERVE WHITESPACE) WHERE id = ’001’;
Aplicación COBOL de SQL incorporado: EXEC 01 01 01 EXEC
SQL BEGIN DECLARE SECTION END-EXEC. xmlBuf USAGE IS SQL TYPE IS XML as CLOB(5K). clobBuf USAGE IS SQL TYPE IS CLOB(5K). xmlblob USAGE IS SQL TYPE IS XML AS BLOB(5K). SQL END DECLARE SECTION END-EXEC.
* utilizando una variable host XML AS CLOB EXEC SQL SELECT xmlCol INTO :xmlBuf FROM myTable WHERE id = ’001’. EXEC SQL UPDATE myTable SET xmlCol = :xmlBuf WHERE id = ’001’. * utilizando una variable host XML AS BLOB EXEC SQL SELECT xmlCol INTO :xmlblob FROM myTable WHERE id = ’001’. EXEC SQL UPDATE myTable SET xmlCol = :xmlblob WHERE id = ’001’.
Programación SQL XML
45
* utilizando una variable host CLOB EXEC SQL SELECT XMLSERIALIZE(xmlCol AS CLOB(10K)) INTO :clobBuf FROM myTable WHERE id= ’001’. EXEC SQL UPDATE myTable SET xmlCol = XMLPARSE(:clobBuf) PRESERVE WHITESPACE WHERE id = ’001’.
Recomendaciones para el desarrollo de aplicaciones de SQL incorporado con XML: La utilización de XML en aplicaciones de SQL incorporado está sujeta a las siguientes recomendaciones y restricciones. v Las aplicaciones deben acceder a todos los datos XML en formato de serie serializada. – Debe representar todos los datos, incluidos los datos numéricos y de fecha y hora, en su formato de serie serializado. v Los datos XML externalizados están limitados a 2 GB. v Todos los cursores que contienen datos XML son sin bloqueo (cada operación de captación genera una solicitud de servidor de bases de datos). v Cuando las variables host de tipo carácter contienen datos XML serializados, se presupone la utilización del CCSID de la variable host como codificación de los datos, y debe coincidir con cualquier codificación interna que exista en los datos. v Debe especificar un tipo de datos LOB como el tipo base para una variable del lenguaje principal XML. v Al utilizar SQL estático, si se espera un tipo de datos XML en la entrada, el uso de variables host CHAR, VARCHAR, CLOB, DBCLOB y BLOB estará sujeto a una operación XMLPARSE con características de manejo de espacio en blanco predeterminadas ('STRIP WHITESPACE'). Cualquier otro tipo de variable host que no sea XML se rechazará. Identificación de valores XML en un SQLDA: Para indicar que un tipo base alberga datos XML, debe actualizarse el campo sqlname de SQLVAR. v sqlname.length debe ser 8 v Los dos primeros bytes de sqlname.data deben ser X'0000' v El tercer y cuarto bytes de sqlname.data deben ser X'0000' v El quinto byte de sqlname.data debe ser X'01' (al que se hace referencia como el indicador de subtipo XML sólo cuando se cumplen las dos primeras condiciones) v Los restantes bytes deben ser X'000000' Si el indicador de subtipo XML está establecido en un SQLVAR cuyo SQLTYPE no es LOB, se devolverá un error SQL0804 en tiempo de ejecución. Nota: SQL_TYP_XML sólo se puede devolver desde la sentencia DESCRIBE. Este tipo no puede utilizarse para otras solicitudes. La aplicación debe modificar SQLDA para que contenga un tipo binario o de carácter válido y establecer el campo sqlname adecuadamente para indicar que los datos son XML.
Java Java y XML Datos XML en aplicaciones JDBC: En las aplicaciones JDBC, puede almacenar en columnas XML y recuperar datos de columnas XML. En las tablas de base de datos, el tipo de datos integrado XML se utiliza para almacenar datos XML en una columna.
46
IBM i: Programación SQL XML
En las aplicaciones, los datos XML se encuentran en formato de serie serializada. En las aplicaciones JDBC, puede: v Almacenar un documento XML completo en una columna XML mediante los métodos setXXX. v Recuperar un documento XML completo de una columna XML mediante los métodos getXXX. Se pueden utilizar objetos java.sql.SQLXML de JDBC 4.0 para recuperar y actualizar datos de columnas XML. Las invocaciones de métodos de metadatos, tales como ResultSetMetaData.getColumnTypeName, devuelven el valor entero java.sql.Types.SQLXML para una columna de tipo XML. Actualizaciones de columnas XML en aplicaciones JDBC: Cuando actualiza o inserta datos en columnas XML de una tabla de base de datos, los datos de entrada de sus aplicaciones JDBC deben tener el formato de serie de caracteres serializada. La tabla siguiente lista los métodos y los correspondientes tipos de datos de entrada que puede utilizar para insertar datos en columnas XML. Tabla 2. Métodos y tipos de datos para actualizar columnas XML Método
Tipo de datos de entrada
PreparedStatement.setAsciiStream
InputStream
PreparedStatement.setBinaryStream
InputStream
PreparedStatement.setBlob
Blob
PreparedStatement.setBytes
byte[]
PreparedStatement.setCharacterStream
Reader
PreparedStatement.setClob
Clob
PreparedStatement.setObject
byte[], Blob, Clob, SQLXML, InputStream, Reader, String
PreparedStatement.setString
String
La codificación de los datos XML se puede derivar de los datos mismos, conocidos como datos codificados internamente; si se derivan de fuentes externas se conocen como datos codificados externamente. Los datos XML que se envían al servidor de bases de datos como datos binarios se consideran datos codificados internamente. Los datos XML que se envían a la fuente de datos como datos de tipo carácter se tratan como datos codificados externamente. La codificación externa utilizada para aplicaciones Java es siempre la codificación Unicode. Los datos codificados externamente pueden tener una codificación interna. Es decir, los datos se pueden enviar a la fuente de datos como datos de tipo carácter, pero los datos contienen información de codificación. El origen de datos maneja las incompatibilidades entre la codificación interna y externa generando un error si las codificaciones externa e interna son incompatibles. Los datos de las columnas XML se almacenan en el CCSID de la columna XML. El origen de datos maneja la conversión de los datos desde su codificación interna o externa al CCSID de la columna XML. El ejemplo siguiente muestra la inserción de datos de un objeto SQLXML en una columna XML. Los datos son de tipo carácter (String), por lo que la fuente de base de datos trata los datos como codificados externamente. public void insertSQLXML() { Connection con = DriverManager.getConnection(url); SQLXML info = con.createSQLXML; // Crear objeto SQLXML Programación SQL XML
47
PreparedStatement insertStmt = null; String infoData = "..."; cid.setString(cidData); // Llenar objeto SQLXML con datos int cid = 1000; try { sqls = "INSERT INTO CUSTOMER (CID, INFO) VALUES (?, ?)"; insertStmt = con.prepareStatement(sqls); insertStmt.setInt(1, cid); insertStmt.setSQLXML(2, info); // Asignar el valor del objeto SQLXML // a un parámetro de entrada if (insertStmt.executeUpdate() != 1) { System.out.println("insertSQLXML: Ningún registro insertado."); } } catch (IOException ioe) { ioe.printStackTrace(); } catch (SQLException sqle) { System.out.println("insertSQLXML: SQL Exception: " + sqle.getMessage()); System.out.println("insertSQLXML: SQL State: " + sqle.getSQLState()); System.out.println("insertSQLXML: SQL Error Code: " + sqle.getErrorCode()); } }
El ejemplo siguiente muestra la inserción de datos de un archivo en una columna XML. Los datos se insertan como datos binarios, de manera que el servidor de bases de datos respeta la codificación interna. public void insertBinStream() { PreparedStatement insertStmt = null; String sqls = null; int cid = 0; ResultSet rs=null; Statement stmt=null; try { sqls = "INSERT INTO CUSTOMER (CID, INFO) VALUES (?, ?)"; insertStmt = conn.prepareStatement(sqls); insertStmt.setInt(1, cid); File file = new File(fn); insertStmt.setBinaryStream(2, new FileInputStream(file), (int)file.length()); if (insertStmt.executeUpdate() != 1) { System.out.println("insertBinStream: Ningún registro insertado."); } } catch (IOException ioe) { ioe.printStackTrace(); } catch (SQLException sqle) { System.out.println("insertBinStream: SQL Exception: " + sqle.getMessage()); System.out.println("insertBinStream: SQL State: " + sqle.getSQLState()); System.out.println("insertBinStream: SQL Error Code: " + sqle.getErrorCode()); } }
48
IBM i: Programación SQL XML
Recuperación de datos XML en aplicaciones JDBC: En las aplicaciones JDBC, se utilizan los métodos ResultSet.getXXX o ResultSet.getObject para recuperar datos de columnas XML. Al recuperar datos de columnas XML de una tabla de DB2, los datos de salida se encuentran en formato de serie serializada. Puede utilizar una de las técnicas siguientes para recuperar datos XML: v Utilice el método ResultSet.getSQLXML para recuperar los datos. Luego utilice un método SQLXML.getXXX para transformar los datos a un tipo de datos de salida compatible. El método SQLXML.getBinaryStream añade una declaración XML con una especificación de codificación a los datos de salida. Los métodos SQLXML.getString y SQLXML.getCharacterStream no añaden la declaración XML. v Utilice un método ResultSet.getXXX que no sea ResultSet.getObject para recuperar los datos en un tipo que sea compatible. La tabla siguiente muestra los métodos ResultSet y sus correspondientes tipos de datos de salida para recuperar datos XML. Tabla 3. Métodos ResultSet y tipos de datos para recuperar datos XML Método
Tipo de datos de salida
ResultSet.getAsciiStream
InputStream
ResultSet.getBinaryStream
InputStream
ResultSet.getBytes
byte[]
ResultSet.getCharacterStream
Reader
ResultSet.getSQLXML
SQLXML
ResultSet.getString
String
La tabla siguiente muestra los métodos que puede invocar para recuperar datos de un objeto java.sql.SQLXML, los tipos de datos de salida correspondientes y el tipo de codificación utilizado en las declaraciones XML. Tabla 4. Métodos SQLXML y DB2Xml, tipos de datos y especificaciones de codificación añadidas Tipo de declaración de codificación interna XML añadida
Método
Tipo de datos de salida
SQLXML.getBinaryStream
InputStream
Codificación de CCSID de columna XML
SQLXML.getCharacterStream
Reader
Ninguna
SQLXML.getSource
Origen
Ninguna
SQLXML.getString
String
Ninguna
Si la aplicación ejecuta la función XMLSERIALIZE en los datos que se deben devolver, después de la ejecución de la función, los datos tendrán el tipo especificado en la función XMLSERIALIZE, no el tipo de datos XML. Por consiguiente, el controlador maneja los datos como el tipo especificado y pasa por alto cualquier declaración de codificación interna. El ejemplo siguiente muestra la recuperación de datos de una columna XML en un objeto SQLXML y, a continuación, la utilización del método SQLXML.getString para recuperar los datos en una serie.
Programación SQL XML
49
public void fetchToSQLXML() { System.out.println(">> fetchToSQLXML: Get XML data as an SQLXML object " + "using getSQLXML"); PreparedStatement selectStmt = null; String sqls = null, stringDoc = null; ResultSet rs = null; try{ sqls = "SELECT info FROM customer WHERE cid = " + cid; selectStmt = conn.prepareStatement(sqls); rs = selectStmt.executeQuery(); // Obtener metadatos // El tipo de la columna XML es el entero java.sql.Types.OTHER ResultSetMetaData meta = rs.getMetaData(); String colType = meta.getColumnType(1); System.out.println("fetchToSQLXML: Column type = " + colType); while (rs.next()) { // Recuperar los datos XML con getSQLXML. // A continuación escribirlo en una serie de texto con // codificación ISO-10646-UCS-2 interna explícita. java.sql.SQLXML xml = rs.getSQLXML(1); System.out.println (xml.getString()); } rs.close(); } catch (SQLException sqle) { System.out.println("fetchToSQLXML: SQL Exception: " + sqle.getMessage()); System.out.println("fetchToSQLXML: SQL State: " + sqle.getSQLState()); System.out.println("fetchToSQLXML: SQL Error Code: " + sqle.getErrorCode()); } }
El ejemplo siguiente muestra la recuperación de datos de una columna XML en una variable String. public void fetchToString() { System.out.println(">> fetchToString: Get XML data " + "using getString"); PreparedStatement selectStmt = null; String sqls = null, stringDoc = null; ResultSet rs = null; try{ sqls = "SELECT info FROM customer WHERE cid = " + cid; selectStmt = conn.prepareStatement(sqls); rs = selectStmt.executeQuery(); // Obtener metadatos // El tipo de la columna XML es el entero java.sql.Types.OTHER ResultSetMetaData meta = rs.getMetaData(); String colType = meta.getColumnType(1); System.out.println("fetchToString: Column type = " + colType); while (rs.next()) { stringDoc = rs.getString(1); System.out.println("Document contents:"); System.out.println(stringDoc); } catch (SQLException sqle) { System.out.println("fetchToString: SQL Exception: " + sqle.getMessage()); System.out.println("fetchToString: SQL State: " +
50
IBM i: Programación SQL XML
sqle.getSQLState()); System.out.println("fetchToString: SQL Error Code: " + sqle.getErrorCode()); } }
Invocación de rutinas con parámetros XML en aplicaciones Java: Los procedimientos almacenados de SQL o externos y las funciones definidas por el usuario externas pueden incluir parámetros XML. Para los procedimientos de SQL, los parámetros de la definición de procedimiento almacenado tienen el tipo XML. En los procedimientos almacenados externos y funciones definidas por el usuario, los parámetros XML de la definición de rutina tienen el tipo XML AS. Cuando invoca un procedimiento almacenado o una función definida por el usuario que tiene parámetros XML, necesita utilizar un tipo de datos compatible en la sentencia de invocación. Para invocar una rutina con parámetros de entrada XML desde un programa JDBC, utilice parámetros del tipo java.sql.SQLXML. Para registrar parámetros de salida XML, registre los parámetros como el tipo java.sql.Types.SQLXML. Ejemplo: programa JDBC que llama a un procedimiento almacenado que utiliza tres parámetros XML: un parámetro IN, un parámetro OUT y un parámetro INOUT. Este ejemplo requiere JDBC 4.0. java.sql.SQLXML in_xml = xmlvar; java.sql.SQLXML out_xml = null; java.sql.SQLXML inout_xml = xmlvar; // Declarar un parámetro XML de entrada, // de salida y de entrada/salida Connection con; CallableStatement cstmt; ResultSet rs; ... stmt = con.prepareCall("CALL SP_xml(?,?,?)"); // Crear un objeto CallableStatement cstmt.setObject (1, in_xml); // Establecer parámetro de entrada cstmt.setObject (3, inout_xml); // Establecer parámetro E/S cstmt.registerOutParameter (2, java.sql.Types.SQLXML); // Registrar parámetros de entrada y de salida cstmt.registerOutParameter (3, java.sql.Types.SQLXML); cstmt.executeUpdate(); // Llamar al procedimiento almacenado out_xml = cstmt.getSQLXML(2); // Obtener el valor del parámetro OUT inout_xml = cstmt.getSQLXML(3); // Obtener el valor del parámetro INOUT System.out.println("Valores de parámetros de llamada a SP_xml: "); System.out.println("Valor de parámetro de salida "); MyUtilities.printString(out_xml.getString()); // Utilizar el método SQLXML.getString // para convertir el valor out_xml // a una serie para impresión. // Llamar a un método definido por el usuario denominado // printString (no se muestra) para imprimir // el valor. System.out.println("Valor del parámetro INOUT "); MyUtilities.printString(inout_xml.getString()); // Utilizar el método SQLXML.getString // para convertir el valor inout_xml // a una serie para impresión. // Llamar a un método definido por el usuario denominado // printString (no se muestra) para imprimir // el valor.
Ejemplo: programa SQLJ que llama un procedimiento almacenado que utiliza tres parámetros XML: un parámetro IN, un parámetro OUT y un parámetro INOUT. Este ejemplo requiere JDBC 4.0. Programación SQL XML
51
java.sql.SQLXML in_xml = xmlvar; java.sql.SQLXML out_xml = null; java.sql.SQLXML inout_xml = xmlvar; // Declarar un parámetro XML de entrada, // de salida y de entrada/salida ... #sql [myConnCtx] {CALL SP_xml(:IN in_xml, :OUT out_xml, :INOUT inout_xml)}; // Invocar el procedimiento almacenado System.out.println("Valores de parámetros de llamada a SP_xml: "); System.out.println("Valor de parámetro de salida "); MyUtilities.printString(out_xml.getString()); // Utilizar el método SQLXML.getString // para convertir el valor out_xml // a una serie para impresión. // Llamar a un método definido por el usuario denominado // printString (no se muestra) para imprimir // el valor. System.out.println("Valor del parámetro INOUT "); MyUtilities.printString(inout_xml.getString()); // Utilizar el método SQLXML.getString // para convertir el valor inout_xml // a una serie para impresión. // Llamar a un método definido por el usuario denominado // printString (no se muestra) para imprimir // el valor.
Datos XML en aplicaciones SQLJ: En las aplicaciones SQLJ, puede almacenar en columnas XML y recuperar datos de columnas XML. En las tablas de DB2, el tipo de dato incorporado XML se utiliza para almacenar datos XML en una columna. En las aplicaciones, los datos XML se encuentran en formato de serie serializada. En las aplicaciones SQLJ, puede: v Almacenar un documento XML completo en una columna XML mediante sentencias INSERT o UPDATE. v Recuperar un documento XML completo de una columna XML mediante iteradores o sentencias SELECT de una sola fila. Se pueden utilizar objetos java.sql.SQLXML de JDBC 4.0 para recuperar y actualizar datos de columnas XML. Las invocaciones de métodos de metadatos, tales como ResultSetMetaData.getColumnTypeName, devuelven el valor entero java.sql.Types.SQLXML para una columna de tipo XML. Actualizaciones de columna XML en aplicaciones SQLJ: Cuando actualiza o inserta datos en columnas XML de una tabla en una aplicación SQLJ, los datos de entrada deben tener el formato de serie de caracteres serializada. Los tipos de datos de expresión de lenguaje principal que se pueden utilizar para actualizar las columnas XML son: v java.sql.SQLXML (requiere SQLJ Versión 4.0 o posterior) v String v byte v Blob v Clob
52
IBM i: Programación SQL XML
v sqlj.runtime.AsciiStream v sqlj.runtime.BinaryStream v sqlj.runtime.CharacterStream Para los tipos de corrientes, debe utilizarse la expresión de lenguaje principal sqlj.runtime.tipoStream, en lugar de una expresión de lenguaje principal java.io.typeInputStream, a fin de pasar la longitud de la corriente al controlador JDBC. La codificación de los datos XML se puede derivar de los datos mismos, conocidos como datos codificados internamente; si se derivan de fuentes externas se conocen como datos codificados externamente. Los datos XML que se envían al servidor de bases de datos como datos binarios se consideran datos codificados internamente. Los datos XML que se envían a la fuente de datos como datos de tipo carácter se tratan como datos codificados externamente. Para JVM, se utiliza la codificación externa por omisión. La codificación externa utilizada para aplicaciones Java es siempre la codificación Unicode. Los datos codificados externamente pueden tener una codificación interna. Es decir, los datos se pueden enviar a la fuente de datos como datos de tipo carácter, pero los datos contienen información de codificación. El origen de datos maneja las incompatibilidades entre la codificación interna y externa generando un error si las codificaciones externa e interna son incompatibles. Los datos de las columnas XML se almacenan en el CCSID de la columna XML. Supongamos que utiliza la sentencia siguiente para insertar datos de la expresión de lenguaje principal de serie xmlString en una columna XML de una tabla. xmlString es un tipo de carácter, por lo que se utiliza su codificación externa. #sql [ctx] {INSERT INTO CUSTACC VALUES (1, :xmlString)};
Expresión de lenguaje principal sqlj.runtime.CharacterStream: supongamos que construye una expresión de lenguaje principal sqlj.runtime.CharacterStream e inserta datos de la expresión de lenguaje principal sqlj.runtime.CharacterStream en una columna XML de una tabla. java.io.StringReader xmlReader = new java.io.StringReader(xmlString); sqlj.runtime.CharacterStream sqljXmlCharacterStream = new sqlj.runtime.CharacterStream(xmlReader, xmlString.length()); #sql [ctx] {INSERT INTO CUSTACC VALUES (4, :sqljXmlCharacterStream)};
sqljXmlCharacterStream es un tipo de carácter, por lo que se utiliza su codificación externa. Supongamos que recupera un documento de una columna XML en una expresión de lenguaje principal java.sql.SQLXML e inserta los datos en una columna XML de una tabla. java.sql.ResultSet rs = s.executeQuery ("SELECT * FROM CUSTACC"); rs.next(); java.sql.SQLXML xmlObject = (java.sql.SQLXML)rs.getObject(2); #sql [ctx] {INSERT INTO CUSTACC VALUES (6, :xmlObject)};
Una vez que haya recuperado los datos, seguirán estando codificados en UTF-8. En consecuencia, cuando inserte los datos en otra columna XML, no se llevará a cabo ninguna conversión. Recuperación de datos XML en aplicaciones de SQLJ: Cuando recupera datos procedentes de columnas XML de una tabla de base de datos en una aplicación SQLJ, los datos de salida se deben serializar explícita o implícitamente. Los tipos de datos de iterador o expresión de lenguaje principal que puede utilizar para recuperar datos de las columnas XML son: Programación SQL XML
53
v v v v v
java.sql.SQLXML (SQLJ Versión 4.0) String byte[] sqlj.runtime.AsciiStream sqlj.runtime.BinaryStream
v sqlj.runtime.CharacterStream Si la aplicación no llama a la función XMLSERIALIZE antes de la recuperación de datos, los datos se convierten de UTF-8 a la codificación de aplicación externa para los tipos de datos de caracteres o la codificación interna para los tipos de datos binarios. No se ha añadido una declaración XML. Si la expresión de lenguaje principal es un objeto de tipo java.sql.SQLXML o com.ibm.db2.jcc.DB2Xml, es necesario invocar un método adicional para recuperar los datos de este objeto. El método que invoque determina la codificación de los datos de salida y si se añade una declaración XML con una especificación de la codificación. La tabla siguiente muestra los métodos que puede invocar para recuperar datos de un objeto java.sql.SQLXML o com.ibm.db2.jcc.DB2Xml, los tipos de datos de salida correspondientes y el tipo de codificación utilizado en las declaraciones XML. Tabla 5. Métodos SQLXML y DB2Xml, tipos de datos y especificaciones de codificación añadidas Tipo de declaración de codificación interna XML añadida
Método
Tipo de datos de salida
SQLXML.getBinaryStream
InputStream
Codificación de CCSID de columna XML
SQLXML.getCharacterStream
Reader
Ninguna
SQLXML.getSource
Origen
Ninguna
SQLXML.getString
String
Ninguna
Si la aplicación ejecuta la función XMLSERIALIZE en los datos que se deben devolver, después de la ejecución de la función, los datos tendrán el tipo especificado en la función XMLSERIALIZE, no el tipo de datos XML. Por consiguiente, el controlador maneja los datos como el tipo especificado y pasa por alto cualquier declaración de codificación interna. Supongamos que recupera datos de una columna XML en una expresión de lenguaje principal de tipo String. #sql iterator XmlStringIter (int, String); #sql [ctx] siter = {SELECT C1, CADOC from CUSTACC}; #sql {FETCH :siter INTO :row, :outString};
El tipo String es un tipo de carácter, por lo que los datos se convierten de UTF-8 a la codificación externa y se devuelven sin ninguna declaración XML. Supongamos que recupera datos de una columna XML en una expresión de lenguaje principal byte[]. #sql iterator XmlByteArrayIter (int, byte[]); XmlByteArrayIter biter = null; #sql [ctx] biter = {SELECT c1, CADOC from CUSTACC}; #sql {FETCH :biter INTO :row, :outBytes};
El tipo byte[] es un tipo binario, por lo que no se produce ninguna conversión de datos desde la codificación UTF-8, y los datos se devuelven sin ninguna declaración XML.
54
IBM i: Programación SQL XML
Supongamos que recupera un documento de una columna XML en una expresión de lenguaje principal java.sql.SQLXML, pero necesita los datos en una corriente binaria. #sql iterator SqlXmlIter (int, java.sql.SQLXML); SqlXmlIter SQLXMLiter = null; java.sql.SQLXML outSqlXml = null; #sql [ctx] SqlXmlIter = {SELECT c1, CADOC from CUSTACC}; #sql {FETCH :SqlXmlIter INTO :row, :outSqlXml}; java.io.InputStream XmlStream = outSqlXml.getBinaryStream();
La sentencia FETCH recupera los datos y los coloca en el objeto SQLXML según la codificación UTF-8. SQLXML.getBinaryStream almacena los datos en una corriente binaria.
Rutinas Rutinas y XML Soporte de XML en procedimientos SQL: Los procedimientos SQL admiten parámetros y variables de tipo de datos XML. También puede utilizarse en sentencias SQL, del mismo modo que las variables de cualquier otro tipo de datos. En el siguiente ejemplo se muestra la declaración, el uso y la asignación de los parámetros y variables XML en un procedimiento SQL: CREATE TABLE T1(C1 XML) ; CREATE PROCEDURE proc1(IN parm1 XML, IN parm2 VARCHAR(32000)) LANGUAGE SQL BEGIN DECLARE var1 XML; /* insertar el valor de parm1 en la tabla T1 */ INSERT INTO T1 VALUES(parm1); /* analizar valor del parámetro parm2 y asignarlo a una variable */ SET var1 = XMLPARSE(document parm2 preserve whitespace); /* insertar la variable var1 en tabla T1 INSERT INTO T1 VALUES(var1); END ;
En el ejemplo anterior hay una tabla T1 con una columna XML. El procedimiento SQL acepta dos parámetros, parm1 y parm2. parm1 es del tipo de datos XML. Dentro del procedimiento SQL, se declara una variable XML denominada var1. El valor del parámetro parm2 se analiza utilizando la función XMLPARSE y se asigna a la variable XML var1. A continuación, el valor de la variable XML también se inserta en la columna C1 de la tabla T1. Efecto de los compromisos y retroacciones en valores de parámetros y variables XML de procedimientos de SQL: Los compromisos y retrotracciones de los procedimientos de SQL afectan a los valores de los parámetros y variables de tipo de datos XML. Durante la ejecución de los procedimientos SQL, al producirse una operación de confirmación o retrotracción, los valores asignados a las variables XML y a los parámetros XML dejarán de estar disponibles. Los intentos de hacer referencia a una variable SQL o parámetro SQL del tipo de datos XML después de una operación de compromiso o retrotracción provocarán un error. Para hacer referencia de modo satisfactorio a parámetros y variables XML después de una operación de compromiso o retrotracción, antes deben asignárseles nuevos valores. Programación SQL XML
55
Tenga en cuenta la disponibilidad de los valores de las variables y parámetros XML al añadir sentencias ROLLBACK y COMMIT a los procedimientos de SQL. Soporte para el tipo de datos XML en rutinas externas: Procedimientos y funciones externos escritos en lenguajes de programación que dan soporte a parámetros y variables de tipo de datos XML: Estos lenguajes de programación incluyen: v v v v v
ILE RPG ILE COBOL C C++ Java
Los valores de tipo de datos XML se representan en el código de la rutina externa de la misma manera que los tipos de datos de carácter, gráficos y binarios. Al declarar los parámetros de la rutina externa del tipo de datos XML, las sentencias CREATE PROCEDURE y CREATE FUNCTION que se utilizarán para crear las rutinas en la base de datos deben especificar que el tipo de datos XML debe almacenarse como un tipo de datos de carácter, gráfico o binario. El tamaño del valor de carácter, gráfico o binario debe ser cercano al tamaño del documento XML representado por el parámetro XML. A continuación figura una sentencia CREATE PROCEDURE de un procedimiento externo implementado en el lenguaje de programación C con un parámetro XML llamado parm1: CREATE PROCEDURE myproc(IN parm1 XML AS CLOB(2M), IN parm2 VARCHAR(32000)) LANGUAGE C FENCED PARAMETER STYLE SQL EXTERNAL NAME ’mylib.myproc’;
Hay que tener en cuenta consideraciones parecidas al crear funciones definidas por usuario (UDF) externas, como se ve en el siguiente ejemplo: CREATE FUNCTION myfunc (IN parm1 XML AS CLOB(2M)) RETURNS SMALLINT LANGUAGE C PARAMETER STYLE SQL DETERMINISTIC NOT FENCED NULL CALL NO SQL NO EXTERNAL ACTION EXTERNAL NAME ’mylib1.myfunc’
En el código de las rutinas externas, los valores de los parámetros y variables XML se acceden, establecen y modifican de la misma manera que en las aplicaciones de bases de datos. Ejemplo: Soporte de XML en procedimientos Java (JDBC): Una vez comprendidos los fundamentos de los procedimientos Java y la programación en Java utilizando la interfaz de programación de aplicaciones (API) JDBC, puede empezar a crear y utilizar procedimientos Java que consulten datos XML. Este ejemplo de procedimiento Java ilustra: v Sentencia CREATE PROCEDURE para un procedimiento del estilo de parámetros JAVA
56
IBM i: Programación SQL XML
v El código fuente para un procedimiento del estilo de parámetros JAVA v Los parámetros de entrada y salida de tipo de datos XML Archivo de código externo Java En el ejemplo se muestra una implementación de procedimiento Java. El ejemplo se compone de dos partes: la sentencia CREATE PROCEDURE y la implementación de código Java externo del procedimiento desde el que se puede crear la clase Java asociada. El archivo fuente Java que contiene las implementaciones de procedimientos de los ejemplos siguientes se denomina stpclass.java y está incluido en un archivo JAR denominado myJAR. El archivo tiene el formato siguiente: Formato del archivo de código externo Java using System; import java.lang.*; import java.io.*; import java.sql.*; import java.util.*; public class stpclass { ... // Implementaciones de procedimientos Java ... }
Es importante tener en cuenta el nombre del archivo de clase y el nombre de JAR que contenga una implementación de procedimiento dada. Estos nombres son importantes, porque la cláusula EXTERNAL de la sentencia CREATE PROCEDURE de cada procedimiento debe especificar esta información a fin de que DB2 pueda localizar la clase en tiempo de ejecución. Ejemplo: Procedimiento del estilo de parámetros JAVA con parámetros XML Este ejemplo muestra lo siguiente: v Sentencia CREATE PROCEDURE para un procedimiento del estilo de parámetros JAVA v Código Java para un procedimiento del estilo de parámetros JAVA con parámetros XML Este procedimiento toma un parámetro de entrada, inXML, inserta una fila que incluye dicho valor en una tabla, consulta datos XML utilizando una sentencia SQL y una expresión XQuery y establece dos parámetros de salida outXML1 y outXML2. Código para crear un procedimiento JAVA de estilo de parámetros con parámetros XML CREATE PROCEDURE xmlProc1 ( IN inNUM INTEGER, IN inXML XML as CLOB (1K), OUT out1XML XML as CLOB (1K), OUT out2XML XML as CLOB (1K) ) DYNAMIC RESULT SETS 0 DETERMINISTIC LANGUAGE JAVA PARAMETER STYLE JAVA MODIFIES SQL DATA FENCED THREADSAFE DYNAMIC RESULT SETS 0 PROGRAM TYPE SUB NO DBINFO EXTERNAL NAME ’stpclass.xmlProc1’;
Programación SQL XML
57
public void xmlProc1(int inNum, CLOB inXML , CLOB [] out1XML, ) throws Exception { Connection con = DriverManager.getConnection("jdbc:default:connection"); // Insertar datos incluyendo el valor de parámetro XML en una tabla String query = "INSERT INTO xmlDataTable (num, inXML ) VALUES ( ?, ? )" ; String xmlString = inXML.getCharacterStream() ; stmt = con.prepareStatement(query); stmt.setInt(1, inNum); stmt.setString (2, xmlString ); stmt.executeUpdate(); stmt.close(); // Consultar y recuperar un solo valor XML de una tabla utilizando SQL query = "SELECT xdata from xmlDataTable WHERE num = ? " ; stmt = con.prepareStatement(query); stmt.setInt(1, inNum); ResultSet rs = stmt.executeQuery(); if ( rs.next() ) { out1Xml[0] = (CLOB) rs.getObject(1); } rs.close() ; stmt.close(); return ; }
Ejemplo: Soporte de XML en procedimientos C: Una vez comprendidos los conceptos básicos de los procedimientos, los fundamentos de las rutinas C y XML, puede empezar a crear y utilizar procedimientos C con características XML. El ejemplo que hay a continuación muestra un procedimiento de C con parámetros del tipo XML así como el modo de actualizar y consultar datos XML. Código C para un procedimiento de estilo parámetros SQL con características XML Este ejemplo muestra lo siguiente: v Sentencia CREATE PROCEDURE para un procedimiento del estilo de parámetros SQL v Código C para un procedimiento del estilo de parámetros SQL con parámetros XML Este procedimiento recibe dos parámetros de entrada. El primer parámetro de entrada se denomina inNum y es del tipo INTEGER. El segundo parámetro de entrada se denomina inXML y es del tipo XML. Los valores de los parámetros de entrada se utilizan para insertar una fila en la tabla xmlDataTable. A continuación, se recupera un valor XML utilizando una sentencia SQL. El valor XML recuperado se asigna al parámetro out1XML. No se devuelven conjuntos de resultados. CREATE PROCEDURE xmlProc1 ( IN inNUM INTEGER, IN inXML XML as CLOB (1K), OUT out1XML XML as CLOB (1K) ) LANGUAGE C PARAMETER STYLE SQL DYNAMIC RESULT SETS 0
58
IBM i: Programación SQL XML
DETERMINISTIC MODIFIES SQL DATA PROGRAM TYPE SUB EXTERNAL NAME ’xmlProc1’ ; //************************************************************************* // Procedimiento almacenado: xmlProc1 // // Finalidad: insertar datos XML en una columna XML // // Parámetros: // // IN: inNum -- la secuencia de datos XML que debe insertarse en la tabla xmldata // inXML -- datos XML que deben insertarse // OUT: out1XML -- datos XML devueltos - valor recuperado mediante SQL //************************************************************************* #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" #endif SQL_API_RC SQL_API_FN testSecA1(sqlint32* inNum, SQLUDF_CLOB* inXML, SQLUDF_CLOB* out1XML, SQLUDF_NULLIND *inNum_ind, SQLUDF_NULLIND *inXML_ind, SQLUDF_NULLIND *out1XML_ind, SQLUDF_TRAIL_ARGS) { char *str; FILE *file; EXEC SQL INCLUDE SQLCA; EXEC SQL BEGIN DECLARE SECTION; sqlint32 hvNum1; SQL TYPE IS XML AS CLOB(200) hvXML1; SQL TYPE IS XML AS CLOB(200) hvXML2; EXEC SQL END DECLARE SECTION; /* Comprobar indicadores nulos para parámetros de entrada */ if ((*inNum_ind < 0) || (*inXML_ind < 0)) { strcpy(sqludf_sqlstate, "38100"); strcpy(sqludf_msgtext, "Entrada nula recibida"); return 0; } /* Copiar parámetros de entrada en variables host */ hvNum1 = *inNum; hvXML1.length = inXML->length; strncpy(hvXML1.data, inXML->data, inXML->length); /* Ejecutar sentencia SQL */ EXEC SQL INSERT INTO xmlDataTable (num, xdata) VALUES (:hvNum1, :hvXML1); /* Ejecutar sentencia SQL */ EXEC SQL SELECT xdata INTO :hvXML2 FROM xmlDataTable WHERE num = :hvNum1; Programación SQL XML
59
exit: /* Establecer código de retorno de salida */ *outReturnCode = sqlca.sqlcode; *outReturnCode_ind = 0; return 0; }
Codificación de datos XML La codificación de datos XML se puede derivar de los datos mismos, conocidos como datos codificados internamente; si se derivan de fuentes externas se conocen como datos codificados externamente. El tipo de datos de la aplicación que se utiliza para intercambiar los datos XML entre la aplicación y la columna XML determina cómo se deriva la codificación. v Los datos XML que se encuentran en tipos de datos de aplicación de carácter o gráficos se consideran codificados externamente. Como datos de carácter y gráficos, los datos XML que se encuentran en estos tipos de datos se consideran codificados en el CCSID declarado de la variable del lenguaje principal. v Los datos XML que se encuentran en un tipo de datos de aplicación binario o datos binarios que se encuentran en un tipo de datos de carácter se consideran codificados internamente. Los datos XML codificados externamente pueden contener codificación interna, como por ejemplo cuando un documento XML de un tipo de datos de carácter contiene una declaración de codificación. El gestor de bases de datos comprueba la codificación interna de los datos codificados externamente enviados a una base de datos DB2. El CCSID efectivo que está asociado con la codificación interna debe coincidir con la codificación externa; de lo contrario, se produce un error.
Consideraciones sobre codificación al almacenar o pasar datos XML Los datos XML deben estar codificados correctamente para poder almacenarlos en una tabla DB2. Debe tenerse en cuenta la codificación cuando los datos se recuperan de la tabla y se utilizan con procedimientos almacenados o funciones DB2 definidas por el usuario, o cuando se utilizan con aplicaciones Java externas. Consideraciones de codificación para la entrada de datos XML en una base de datos: La codificación interna y externa debe tenerse en cuenta al almacenar datos XML en una tabla de DB2. Deben observarse las reglas siguientes: v Para los datos XML codificados externamente (datos que se envían al servidor de bases de datos utilizando tipos de datos de carácter), cualquier declaración codificada internamente debe coincidir con la codificación externa; de lo contrario se produce un error y el gestor de bases de datos rechaza el documento. v Para los datos XML codificados internamente (datos que se envían al servidor de bases de datos utilizando tipos de datos binarios), la aplicación debe asegurarse de que los datos contienen información de codificación exacta. Consideraciones de codificación para la recuperación de datos XML de una base de datos: Al recuperar datos XML de una tabla de DB2, debe evitar la pérdida y el truncamiento de datos. La pérdida de datos puede producirse cuando los caracteres de los datos de origen no se pueden representar en la codificación de los datos de destino. El truncamiento puede producirse cuando la conversión al tipo de datos de destino provoca la expansión de los datos.
60
IBM i: Programación SQL XML
Consideraciones de codificación para pasar datos XML en parámetros de rutinas: En un sistema de base de datos DB2, están disponibles varios tipos de datos XML para los parámetros de un procedimiento almacenado o definición de función definida por el usuario. Están disponibles los siguientes tipos de datos XML: XML
Para procedimientos y funciones SQL.
XML AS Para procedimientos externos y funciones externas definidas por el usuario. Los datos de los parámetros XML AS están sujetos a la conversión de caracteres. Puede utilizarse cualquier tipo de datos de carácter o gráficos de la aplicación para los parámetros de la aplicación de que realiza la llamada, pero los datos de origen no deben contener una declaración de codificación. Pueden producirse conversiones de CCSID adicionales, que pueden provocar que la información de codificación sea inexacta. Si los datos se analizan con mayor detalle en la aplicación, puede producirse la corrupción de los datos. Consideraciones de codificación para datos XML en aplicaciones JDBC y SQLJ: Generalmente, existen menos consideraciones de codificación XML para las aplicaciones Java que para las aplicaciones de SQL incorporado o CLI. Aunque las consideraciones de codificación para datos XML codificados internamente son las mismas para todas las aplicaciones, la situación se simplifica para los datos codificados externamente en aplicaciones Java debido a que el CCSID de la aplicación siempre es Unicode. Recomendaciones generales para la entrada de datos XML en aplicaciones Java v Si los datos de entrada se encuentran en un archivo, lea los datos en una corriente binaria (setBinaryStream), de modo que el gestor de bases de datos los procese como datos codificados internamente. v Si los datos de entrada se encuentran en una variable de aplicación Java, la elección del tipo de variable de aplicación determina si el gestor de bases de datos DB2 utiliza alguna codificación interna. Si especifica los datos como un tipo de carácter (por ejemplo, setString), el gestor de bases de datos convierte los datos de UTF-16 (el CCSID de la aplicación) al CCSID de la columna XML antes de almacenarlos. Recomendaciones generales para la salida de datos XML en aplicaciones Java v Si almacena los datos XML en un archivo como datos no binarios, debe añadir codificación interna XML a los datos de salida. La codificación del sistema de archivos puede no ser Unicode, de modo que los datos de tipo serie pueden experimentar una conversión cuando se almacenan en el archivo. En el caso de una función XMLSERIALIZE explícita con INCLUDING XMLDECLARATION, el servidor de bases de datos añade la codificación y el controlador JDBC no la modifica. v Si la aplicación envía los datos de salida a un analizador XML, debe recuperar los datos en una variable de aplicación binaria, con la codificación UTF-8, UCS-2 o UTF-16.
Efectos de la codificación y serialización XML sobre la conversión de datos El método de especificación de la codificación de los datos XML, interna o externamente, y el método de serialización XML afectan a la conversión de los datos XML al pasar los datos entre una base de datos y una aplicación.
Programación SQL XML
61
Escenarios de codificación para la entrada de datos XML codificados internamente en una base de datos: Los ejemplos siguientes muestran cómo afecta la codificación interna a la conversión y truncamiento de datos durante la entrada de datos XML en una columna XML. En general, el uso de un tipo de datos de aplicación binario minimiza los problemas de conversión de página de códigos durante la entrada en una base de datos. Escenario 1 Origen de codificación
Valor
Codificación de datos Datos de entrada UTF-8 Unicode, con o sin una declaración de codificación XML o UTF-8 BOM Tipo de datos de variable host
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS BLOB) PRESERVE WHITESPACE))
Conversión de caracteres: Ninguna. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenario 2 Origen de codificación
Valor
Codificación de datos Datos de entrada UTF-16 Unicode que contienen una declaración de codificación XML o UTF-16 BOM Tipo de datos de variable host
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS BLOB) PRESERVE WHITESPACE))
Conversión de caracteres: el servidor de bases de datos DB2 convierte los datos de UTF-16 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Ninguno.
62
IBM i: Programación SQL XML
Escenario 3 Origen de codificación
Valor
Codificación de datos Datos de entrada ISO-8859-1 que contienen una declaración de codificación XML Tipo de datos de variable host
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS BLOB) PRESERVE WHITESPACE))
Conversión de caracteres: el sistema de bases de datos DB2 convierte los datos del CCSID 819 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenario 4 Origen de codificación
Valor
Codificación de datos Datos de entrada Shift_JIS que contienen una declaración de codificación XML Tipo de datos de variable host
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS BLOB) PRESERVE WHITESPACE))
Conversión de caracteres: el sistema de bases de datos DB2 convierte los datos del CCSID 943 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenarios de codificación para la entrada de datos XML codificados externamente en una base de datos: Los ejemplos siguientes muestran cómo afecta la codificación externa a la conversión y truncamiento de datos durante la entrada de datos XML en una columna XML. En general, al utilizar un tipo de datos de aplicación de carácter, no hay ningún problema con la conversión del CCSID durante la entrada en una base de datos.
Programación SQL XML
63
Sólo los escenarios 1 y 2 son aplicables a Java, ya que la página de códigos de aplicación para Java es siempre Unicode porque las series de caracteres en Java son siempre Unicode. Escenario 1 Origen de codificación
Valor
Codificación de datos Datos de entrada UTF-8 Unicode, con o sin una declaración de codificación adecuada o BOM Tipo de datos de variable host
Carácter
CCSID declarado de variable host
1208 (UTF-8)
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS CLOB) PRESERVE WHITESPACE))
Conversión de caracteres: Ninguna. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenario 2 Origen de codificación
Valor
Codificación de datos Datos de entrada UTF-16 Unicode, con o sin una declaración de codificación adecuada o BOM Tipo de datos de variable host
Gráfico
CCSID declarado de variable host
1200 o 13488
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS DBCLOB) PRESERVE WHITESPACE))
Conversión de caracteres: el sistema de bases de datos DB2 convierte los datos de UTF-16 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Puede producirse durante la conversión de UTF-16 a UTF-8 debido a la expansión. Escenario 3 Origen de codificación
Valor
Codificación de datos Datos de entrada ISO-8859-1, con o sin una declaración de codificación adecuada Tipo de datos de variable host
64
Carácter
IBM i: Programación SQL XML
Origen de codificación CCSID declarado de variable host
Valor 819
Ejemplo de sentencias de entrada: INSERT INTO T1 (XMLCOL) VALUES (?) INSERT INTO T1 (XMLCOL) VALUES (XMLPARSE(DOCUMENT CAST(? AS CLOB) PRESERVE WHITESPACE))
Conversión de caracteres: el sistema de bases de datos DB2 convierte los datos del CCSID 819 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenario 4 Origen de codificación
Valor
Codificación de datos Datos de entrada Shift_JIS, con o sin una declaración de codificación adecuada Tipo de datos de variable host
Gráfico
CCSID declarado de variable host
943
Ejemplo de sentencias de entrada: INSERT INTO T1 VALUES (?) INSERT INTO T1 VALUES (XMLPARSE(DOCUMENT CAST(? AS DBCLOB)))
Conversión de caracteres: el sistema de bases de datos DB2 convierte los datos del CCSID 943 a UTF-8 cuando realiza el análisis XML para el almacenamiento en una columna XML UTF-8. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Escenarios de codificación para la recuperación de datos XML con serialización implícita: Los ejemplos siguientes muestran cómo la codificación de destino y la página de códigos de la aplicación afectan a la conversión, el truncamiento y la codificación interna de datos durante la recuperación de datos XML con serialización implícita. Sólo los escenarios 1 y 2 son aplicables a las aplicaciones Java, ya que la página de códigos de aplicación para las aplicaciones Java es siempre Unicode porque las series de caracteres en Java son siempre Unicode.
Programación SQL XML
65
Escenario 1 Origen de codificación
Valor
Codificación de datos UTF-8 Unicode de destino Tipo de datos de variable host de destino
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de salida: SELECT XMLCOL FROM T1
Conversión de caracteres: Ninguna. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Codificación interna en los datos serializados: para aplicaciones que no son Java, se especifica la siguiente declaración XML como prefijo de los datos:
Para las aplicaciones Java, no se añade ninguna declaración de codificación, a menos que convierta los datos como el tipo com.ibm.db2.jcc.DB2Xml y utilice un método getDB2Xmlxxx para recuperar los datos. La declaración que se añade depende del getDB2Xmlxxx que utilice. Escenario 2 Origen de codificación
Valor
Codificación de datos UTF-16 Unicode de destino Tipo de datos de variable host de destino
Gráfico
CCSID declarado de variable host
1200 o 13488
Ejemplo de sentencias de salida: SELECT XMLCOL FROM T1
Conversión de caracteres: los datos se convierten de UTF-8 a UTF-16. Pérdida de datos: Ninguna. Truncamiento: puede producirse durante la conversión de UTF-8 a UTF-16, debido a la expansión. Codificación interna en los datos serializados: para aplicaciones que no sean Java o .NET, los datos tienen como prefijo una marca de orden de bytes (BOM) UTF-16 y la declaración XML siguiente:
66
IBM i: Programación SQL XML
Para las aplicaciones Java, no se añade ninguna declaración de codificación, a menos que convierta los datos como el tipo com.ibm.db2.jcc.DB2Xml y utilice un método getDB2Xmlxxx para recuperar los datos. La declaración que se añade depende del getDB2Xmlxxx que utilice. Escenario 3 Origen de codificación
Valor
Codificación de datos Datos ISO-8859-1 de destino Tipo de datos de variable host de destino
Carácter
CCSID declarado de variable host
819
Ejemplo de sentencias de salida: SELECT XMLCOL FROM T1
Conversión de caracteres: los datos se convierten de UTF-8 a CCSID 819. Pérdida de datos: Posible pérdida de datos. Algunos caracteres UTF-8 no pueden representarse en el CCSID 819. El sistema de base de datos DB2 genera un error. Truncamiento: Ninguno. Codificación interna en los datos serializados:, se especifica la siguiente declaración XML como prefijo de los datos:
Escenario 4 Origen de codificación
Valor
Codificación de datos Datos Windows-31J (superconjunto de Shift_JIS) de destino Tipo de datos de variable host de destino
Gráfico
CCSID declarado de variable host
943
Ejemplo de sentencias de salida: SELECT XMLCOL FROM T1
Conversión de caracteres: los datos se convierten de UTF-8 a CCSID 943. Pérdida de datos: Posible pérdida de datos. Algunos caracteres UTF-8 no pueden representarse en el CCSID 943. El sistema de base de datos DB2 genera un error. Truncamiento: Puede producirse durante la conversión de UTF-8 al CCSID 943 debido a la expansión.
Programación SQL XML
67
Codificación interna en los datos serializados:, se especifica la siguiente declaración XML como prefijo de los datos:
Escenarios de codificación para la recuperación de datos XML con XMLSERIALIZE explícita: Los ejemplos siguientes muestran cómo la codificación de destino y la página de códigos de la aplicación afectan a la conversión, el truncamiento y la codificación interna de datos durante la recuperación de datos XML con una invocación a XMLSERIALIZE explícita. Sólo los escenarios 1 y 2 son aplicables a las aplicaciones Java y .NET, ya que la página de códigos de aplicación para las aplicaciones Java es siempre Unicode. Escenario 1 Origen de codificación
Valor
Codificación de datos UTF-8 Unicode de destino Tipo de datos de variable host de destino
Binario
CCSID declarado de variable host
No aplicable
Ejemplo de sentencias de salida: SELECT XMLSERIALIZE(XMLCOL AS BLOB(1M) INCLUDING XMLDECLARATION) FROM T1
Conversión de caracteres: Ninguna. Pérdida de datos: Ninguna. Truncamiento: Ninguno. Codificación interna en los datos serializados:, se especifica la siguiente declaración XML como prefijo de los datos:
Escenario 2 Origen de codificación
Valor
Codificación de datos UTF-16 Unicode de destino Tipo de datos de variable host de destino
Gráfico
CCSID declarado de variable host
1200 o 13488
Ejemplo de sentencias de salida: SELECT XMLSERIALIZE(XMLCOL AS CLOB(1M) EXCLUDING XMLDECLARATION) FROM T1
68
IBM i: Programación SQL XML
Conversión de caracteres: los datos se convierten de UTF-8 a UTF-16. Pérdida de datos: Ninguna. Truncamiento: puede producirse durante la conversión de UTF-8 a UTF-16, debido a la expansión. Codificación interna en los datos serializados: Ninguna, ya que se especifica EXCLUDING XMLDECLARATION. Si se especifica INCLUDING XMLDECLARATION, la codificación interna indica UTF-8 en lugar de UTF-16. Esto puede generar datos XML que no pueden ser analizados por los procesos de aplicación que se basan en el nombre de la codificación. Escenario 3 Origen de codificación
Valor
Codificación de datos Datos ISO-8859-1 de destino Tipo de datos de variable host de destino
Carácter
CCSID declarado de variable host
819
Ejemplo de sentencias de salida: SELECT XMLSERIALIZE(XMLCOL AS CLOB(1M) EXCLUDING XMLDECLARATION) FROM T1
Conversión de caracteres: los datos se convierten de UTF-8 a CCSID 819. Pérdida de datos: Posible pérdida de datos. Algunos caracteres UTF-8 no pueden representarse en el CCSID 819. Si un carácter no puede representarse en el CCSID 819, el gestor de base de datos DB2 inserta un carácter de sustitución en la salida y emite un aviso. Truncamiento: Ninguno. Codificación interna en los datos serializados: Ninguna, ya que se especifica EXCLUDING XMLDECLARATION. Si se especifica INCLUDING XMLDECLARATION, el gestor de bases de datos añade codificación interna para UTF-8 en lugar de ISO-8859-1. Esto puede generar datos XML que no pueden ser analizados por los procesos de aplicación que se basan en el nombre de la codificación. Escenario 4 Origen de codificación
Valor
Codificación de datos Datos Windows-31J (superconjunto de Shift_JIS) de destino Tipo de datos de variable host de destino
Gráfico
CCSID declarado de variable host
943
Ejemplo de sentencias de salida: SELECT XMLSERIALIZE(XMLCOL AS CLOB(1M) EXCLUDING XMLDECLARATION) FROM T1 Programación SQL XML
69
Conversión de caracteres: los datos se convierten de UTF-8 a CCSID 943. Pérdida de datos: Posible pérdida de datos. Algunos caracteres UTF-8 no pueden representarse en el CCSID 943. Si un carácter no puede representarse en el CCSID 943, el gestor de base de datos inserta un carácter de sustitución en la salida y emite un aviso. Truncamiento: Puede producirse durante la conversión de UTF-8 al CCSID 943 debido a la expansión. Codificación interna en los datos serializados: Ninguna, ya que se especifica EXCLUDING XMLDECLARATION. Si se especifica INCLUDING XMLDECLARATION, la codificación interna indica UTF-8 en lugar de Windows-31J. Esto puede generar datos XML que no pueden ser analizados por los procesos de aplicación que se basan en el nombre de la codificación.
Correlaciones de nombres de codificación con los CCSID efectivos para datos XML almacenados Si los datos que se almacenan en una columna XML se encuentran en una variable de aplicación binaria o son de un tipo XML codificado internamente, el gestor de bases de datos DB2 examina los datos para determinar la codificación. Si los datos tienen una declaración de codificación, el gestor de bases de datos correlaciona el nombre de codificación con un CCSID. La API QlgCvtTextDescToDesc se utiliza para la correlación del nombre de codificación IANA con el CCSID.
Correlaciones de CCSID con nombres de codificación para datos de salida XML serializados Como parte de una operación XMLSERIALIZE implícita o explícita, el gestor de base de datos DB2 añade una declaración de codificación al principio de los datos de salida XML serializados. Esta declaración tiene el formato siguiente:
En general, el identificador de juego de caracteres de la declaración de codificación describe la codificación de los caracteres en la serie de salida. Por ejemplo, cuando se serializan datos XML en el CCSID correspondiente al tipo de datos de la aplicación de destino, la declaración de codificación describe el CCSID de las variables de la aplicación de destino. Siempre que es posible, el gestor de base de datos DB2 elige el nombre de registro IANA para el CCSID, como prescribe el estándar XML. La API QlgCvtTextDescToDesc se utiliza para la correlación el CCSID con el nombre de codificación IANA.
Descomposición de esquemas XML anotados La descomposición de esquemas XML anotados, también conocida como "descomposición" o "fragmentación", es el proceso de almacenar contenido de un documento XML en columnas de tablas relacionales. La descomposición de esquemas XML anotados opera en función de las anotaciones especificadas en un esquema XML. Una vez descompuesto un documento XML, los datos insertados tienen el tipo de datos SQL de la columna en la que se insertan. Un esquema XML consta de uno o más documentos de esquema XML. En la descomposición de esquemas XML anotados, o descomposición basada en esquemas, la descomposición se controla anotando el esquema XML de un documento con anotaciones de descomposición. Estas anotaciones especifican detalles como: v el nombre de la tabla y columna de destino donde deben almacenarse los datos XML v el esquema SQL predeterminado para cuando no se identifique el esquema SQL de una tabla de destino
70
IBM i: Programación SQL XML
v cualquier transformación del contenido antes de que se almacene Consulte el resumen de las anotaciones de descomposición para obtener más ejemplos de lo que puede especificarse mediante estas anotaciones. Los documentos de esquema anotado se deben almacenar y registrar en el repositorio de esquemas XML (XSR). A continuación, el esquema debe habilitarse para la descomposición. Tras el registro satisfactorio del esquema anotado, la descomposición puede realizarse llamando al procedimiento almacenado de descomposición. Los datos del documento XML se validan siempre durante la descomposición. Si la información de un documento XML no cumple con su especificación en un esquema XML, los datos no se insertan en la tabla.
Descomposición de documentos XML con esquemas XML anotados Si desea almacenar partes de un documento XML en columnas de una o más tablas, puede utilizar la descomposición de esquemas XML anotados. Este tipo de descomposición divide un documento XML en fragmentos para el almacenamiento en tablas, en función de las anotaciones especificadas en un esquema XML anotado registrado. Para descomponer documentos XML utilizando esquemas XML anotados: 1. Anote los documentos de esquema con anotaciones de descomposición XML. 2. Registre los documentos de esquema y habilite el esquema para la descomposición. 3. Si alguno de los documentos de esquema registrados que pertenecen al esquema XML ha cambiado, todos los documentos de esquema XML de este esquema XML deben registrarse de nuevo y el esquema XML debe volver a habilitarse para la descomposición. 4. Descomponga el documento XML llamando al procedimiento almacenado SYSPROC.XDBDECOMPXML.
Registro y habilitación de esquemas XML para la descomposición Una vez que un esquema anotado se ha registrado y habilitado satisfactoriamente para la descomposición, puede utilizarlo para descomponer documentos XML. v Asegúrese de que al menos una declaración de elemento o atributo del esquema XML esté anotada con una anotación de descomposición XML. Este elemento o atributo anotado debe ser un descendiente de, o ser él mismo, un elemento global de tipo complejo. Para registrar y habilitar esquemas XML para la descomposición: 1. Llame al procedimiento almacenado XSR_REGISTER, pasando el documento de esquema primario. 2. Si el esquema XML consta de más de un documento de esquema, llame al procedimiento almacenado XSR_ADDSCHEMADOC para cada uno de los documentos de esquema que todavía no se han registrado. 3. Llame al procedimiento almacenado XSR_COMPLETE con el parámetro issuedfordecomposition establecido en 1.
Orígenes de descomposición de esquemas XML anotados La descomposición de esquemas XML anotados puede realizarse en elementos o atributos de un documento XML, y en los resultados de las anotaciones db2-xdb:contentHandling o db2-xdb:expression. La descomposición de esquemas XML anotados admite la descomposición de los siguientes tipos de contenido: v El valor de un atributo o elemento del documento XML. Programación SQL XML
71
v El valor de un elemento del documento XML, donde el contenido exacto depende del valor de la anotación . Los valores de son: text
Datos de tipo carácter del elemento, pero no de sus descendientes
stringValue Datos de tipo carácter del elemento y sus descendientes serializedSubtree Códigos de todo el contenido entre la etiqueta de inicio y la etiqueta de final del elemento v Valores que se generan a través de la anotación db2-xdb:expression: – Un valor que se basa en el contenido de un atributo o elemento correlacionado del documento XML. – Un valor generado que es independiente de los valores del documento XML. – Una constante. Una expresión que se especifica a través de db2-xdb:expression se invoca una vez para cada elemento o atributo con el que está asociado.
anotaciones de descomposición XML La descomposición de esquemas XML anotados se basa en las anotaciones añadidas a los documentos de esquema XML. Estas anotaciones de descomposición funcionan como correlaciones entre los elementos o atributos del documento XML y sus tablas y columnas de destino en la base de datos. El proceso de descomposición hace referencia a estas anotaciones para determinar cómo descomponer un documento XML. Las anotaciones de descomposición XML pertenecen al espacio de nombres http://www.ibm.com/ xmlns/prod/db2/xdb1 y se identifican con el prefijo "db2-xdb" en toda la documentación. Puede seleccionar su propio prefijo; sin embargo, si lo hace, debe enlazar el prefijo al espacio de nombres siguiente: http://www.ibm.com/xmlns/prod/db2/xdb1. El proceso de descomposición sólo reconoce las anotaciones que están bajo este espacio de nombres en el momento de habilitar el esquema XML para la descomposición. El proceso de descomposición sólo reconoce las anotaciones de descomposición si se añaden a declaraciones de elemento y atributo, o como anotaciones globales, en el documento de esquema. Se especifican como atributos o como parte de un elemento hijo de la declaración de elemento o atributo. Las anotaciones añadidas a tipos complejos, referencias u otras construcciones de esquema XML se ignoran. Aunque estas anotaciones existen en los documentos de esquema XML, no afectan a la estructura original del documento de esquema, ni tampoco participan en la validación de los documentos XML. Sólo el proceso de descomposición XML hace referencia a ellas. Dos anotaciones que son características principales del proceso de descomposición son: db2-xdb:rowSet y db2-xdb:column. Estas anotaciones especifican respectivamente la tabla y la columna de destino del valor descompuesto. Estas dos anotaciones deben especificarse en orden para que el proceso de descomposición se complete satisfactoriamente. Otras anotaciones son opcionales, pero pueden utilizarse para controlar con mayor detalle el funcionamiento del proceso de descomposición.
Especificación y ámbito de las anotaciones de descomposición XML Puede especificar anotaciones para la descomposición como declaraciones de elemento o atributo en un documento de esquema XML. Puede hacerlo de cualquiera de las formas siguientes: v Como atributos simples en declaraciones de elemento o atributo v Como elementos hijo estructurados (complejos) de las declaraciones de elemento o atributo simple
72
IBM i: Programación SQL XML
Anotaciones como atributos Las anotaciones especificadas como atributos simples en declaraciones de elemento o atributo se aplican únicamente al elemento o atributo en el que se han especificado. Por ejemplo, las anotaciones de descomposición db2-xdb:rowSet y db2-xdb:column pueden especificarse como atributos. Estas anotaciones se especificarían del siguiente modo:
Las anotaciones db2-xdb:rowSet y db2-xdb:column se aplican sólo a este elemento denominado isbn.
Anotaciones como elementos hijo estructurados Las anotaciones especificadas como elementos hijo estructurados de una declaración de elemento o atributo deben especificarse en el documento de esquema dentro de la jerarquía definida por el esquema XML. Por ejemplo, las anotaciones db2-xdb:rowSet y db2-xdb:column pueden especificarse como elementos hijo (son hijos de la anotación ) de la forma siguiente: TEXTBOOKS ISBN
La especificación de las anotaciones db2-xdb:rowSet y db2-xdb:column como elementos hijo es equivalente a especificarlas como atributos. Aunque más detallada que el método de especificar anotaciones como atributos, la especificación de anotaciones como elementos hijo es necesaria cuando es necesario especificar más de un para un elemento o un atributo; es decir, cuando es necesario especificar varias correlaciones en la misma declaración de elemento o atributo.
Anotaciones globales Cuando una anotación se especifica como hijo del elemento , es una anotación global que se aplica a todos los documentos de esquema XML que forman el esquema XML. Por ejemplo, la anotación indica el esquema SQL predeterminado para todas las tablas no calificadas referenciadas en el esquema XML. debe especificarse como elemento hijo de : admin ...
Esta declaración especifica que todas las tablas no calificadas de todos los documentos de esquema que forman este esquema XML tendrán el esquema SQL "admin".
Anotaciones de descomposición XML - Resumen DB2 da soporte a un conjunto de anotaciones utilizado por el proceso de descomposición del esquema XML anotado para correlacionar los elementos y atributos de un documento XML con las tablas de bases
Programación SQL XML
73
de datos de destino. El siguiente resumen de algunas de las anotaciones de descomposición XML se agrupa por las tareas y acciones que las anotaciones deben realizar. Para obtener más información acerca de una anotación específica, consulte la documentación detallada sobre ella. Tabla 6. Especificación del esquema SQL Acción
Anotación de descomposición XML
Especificar el esquema SQL predeterminado para todas las tablas que no especifican su esquema SQL
db2-xdb:defaultSQLSchema
Especificar un esquema SQL diferente del predeterminado para una tabla específica
db2-xdb:table (elemento hijo )
Tabla 7. Correlación de elementos o atributos XML con tablas base de destino Acción
Anotación de descomposición XML
Correlacionar un único elemento o atributo con un único db2-xdb:rowSet con db2-xdb:column como anotaciones par de columna y tabla de atributo o db2-xdb:rowSetMapping Correlacionar un único elemento o atributo con uno o más pares de columna y tabla diferenciados
db2-xdb:rowSetMapping
Correlacionar varios elementos o atributos con un único par de columna y tabla
db2-xdb:table
Especificar dependencias de orden entre tablas de destino
db2-xdb:rowSetOperationOrder, db2-xdb:rowSet, db2-xdb:order
Tabla 8. Especificación de los datos XML que deben descomponerse Acción
Anotación de descomposición XML
Especificar el tipo de contenido que debe insertarse para un elemento de tipo complejo (texto, serie o marcación)
db2-xdb:contentHandling
Especificar cualquier transformación de contenido que debe aplicarse antes de la inserción
db2-xdb:normalization, db2-xdb:expression, db2-xdb:truncate
Filtrar los datos que deben descomponerse en función del contenido del elemento o del contexto en el que aparece
db2-xdb:condition db2-xdb:locationPath
Anotación de descomposición db2-xdb:defaultSQLSchema La anotación db2-xdb:defaultSQLSchema especifica el esquema SQL predeterminado para todos los nombres de tabla referenciados en el esquema XML que no están calificados explícitamente utilizando la anotación db2-xdb:table.
Tipo de anotación Elemento hijo de que es un hijo de un elemento global .
Cómo se especifica db2-xdb:defaultSQLSchema se especifica de la forma siguiente (donde valor representa un valor válido para la anotación): valor
74
IBM i: Programación SQL XML
...
Espacio de nombres http://www.ibm.com/xmlns/prod/db2/xdb1
Valores válidos Un nombre de esquema SQL ordinario o delimitado. Los nombres de esquema SQL ordinarios o no delimitados no son sensibles a mayúsculas y minúsculas. Para especificar un esquema SQL delimitado, utilice comillas, que suelen utilizarse para delimitar los identificadores de SQL. Los nombres de esquema SQL que contienen los caracteres especiales '