Unidad Didactica 11 - 12 - Operaciones DML y DDL - Protected
Unidad Didactica 11 - 12 - Operaciones DML y DDL - Protected
Unidad Didactica 11 - 12 - Operaciones DML y DDL - Protected
El analizador de XML permite manipular archivos XML desde el lenguaje PL/SQL. De este modo, es posible generar
archivos en dicho formato de composición. Para poder implementar esta funcionalidad, el lenguaje PL/SQL utiliza el
paquete xmldom con el fin de conocer y analizar la estructura del documento XML.
El lenguaje PL/SQL, actualmente empleado por los desarrolladores de aplicaciones sobre Oracle, cuenta así con la
posibilidad de evolucionar hacia el lenguaje XML. El analizador de XML para PL/SQL está escrito en PL/SQL y Java.
Soporta todas las especificaciones publicadas por el consorcio W3C para el estándar 1.0 de XML. Además de cumplir
perfectamente el estándar, el analizador de XML para PL/SQL permite realizar un análisis simplificado del documento,
respetando las directrices del W3C en lo relativo al modelo del documento (DOM, Document Object Model). También
cumple las recomendaciones relativas a XSLT (hojas de estilo) y Xpath.
El analizador se encuentra en el directorio $ORACLE_HOME\xdk\plsql\parser y se incluye como estándar desde la
versión 9i.
El siguiente esquema resume de forma sencilla cómo funciona esta herramienta a la hora de analizar un documento.
Este esquema se aplica en los siguientes ejemplos para conocer la estructura de un documento así como los datos
contenidos en dicho documento.
De este modo, todos los programas tienen la misma estructura para poder analizar un documento XML, que es la
siguiente:
l Creación de un nuevo objeto de tipo Parser usando la función newParser e inicio del análisis del documento XML así
como de su DTD, si está disponible.
l A continuación, tiene que proporcionarse el código fuente XML o DTD, que puede ser de tipo varchar2, CLOB (Character
Large Object Binary) o un archivo.
l Dependiendo del tipo de origen, se aplican los posibles métodos de análisis parse() o parseDTD(), si los datos están
almacenados en un archivo; parseBuffer() o parseDTDBuffer, si los datos están contenidos en un elemento de tipo
varchar2; o parseClob() o parseDTDClob(), si los datos de origen se almacenan en un elemento de tipo CLOB.
l Para los documentos XML que se analizan mediante una de las funciones parse, parseBuffer o parseClob, el resultado
de la ejecución de estos métodos se guarda en un documento accesible mediante getDocument().
l El método freeDocument permite liberar los recursos relativos al documento actualmente utilizados por el analizador,
con el fin de poder analizar otro documento.
l Por último, la instrucción freeParser() permite liberar todos los recursos.
Para comprender el funcionamiento del analizador, evidentemente, el método más sencillo consiste en emplear un
programa simple de ejemplo. No se ilustran todas las funcionalidades del analizador pero, a partir de un ejemplo
funcional, siempre es posible completar los elementos omitidos de forma relativamente sencilla.
El siguiente script permite crear un procedimiento que recibe como parámetro un nombre de archivo xml y lo abre con el fin de
interpretar los datos que contiene. xmlDom y xmlParser son sinónimos públicos de los paquetes DBMS_XMLDOM y
DBMS_XMLPARSER.
-- obtener el documento
doc:=xmlParser.GetDocument(p);
-- liberar el documento
xmlDom.freeDocument(doc);
-- liberar el analizador
xmlParser.freeParser(p);
end;
/
show errors;
La ejecución del procedimiento y el resultado del mismo son los siguientes:
SQL>
XML_DIR es el nombre de un objeto DIRECTORY que se corresponde con el directorio en el que se almacena el archivo
espacioNombre varchar2(50);
-- elementos para generar el resultado
documentoF xmlDom.DOMDocumentFragment;
elementoF xmlDom.DomNode;
begin
-- creación de un nuevo analizador
p:=xmlParser.newParser;
-- obtener el documento
documentoXsl:=xmlParser.getDocument(p);
Este procedimiento permite aplicar una hoja de estilos (XSL) a un documento XML y el resultado se proporciona bajo
la forma de un tercer documento.
La llamada al procedimiento puede realizarse del siguiente modo:
execute aplicarXsl(XML_DIR,’equipo.xml’,’equipo.xsl’,’/tmp/equipo.out’
1. Generación de código XML con DBMS_XMLQuery
Para poder generar un documento XML que contenga los resultados de una consulta simple usando el paquete
DBMS_XMLQuery es necesario llevar a cabo los siguientes cinco pasos:
l Crear un puntero a un contexto llamando al método DBMS_XMLQuery.getCtx y pasándole como parámetro la
consulta.
l Introducir los valores de los distintos parámetros de la consulta usando DBMS_XMLQuery.bind.
l Definir los argumentos opcionales, como el nombre de la etiqueta ROW o ROWSET, el número de filas que se van a
extraer...
l Escribir los datos XML en un elemento CLOB (LOB de caracteres) usando la función DBMS_XMLQuery.getXML. Esta
función puede trabajar con o sin un archivo DTD o un esquema.
l Cerrar el contexto.
a. Generación de código XML a partir de una consulta
El siguiente ejemplo ilustra de forma muy sencilla cómo generar datos en formato XML a partir del contenido de la base de
datos:
set serveroutput on
-- Dar formato XML al resultado de una consulta
declare
contextConsulta DBMS_XMLQuery.ctxType;
resultado CLOB;
begin
-- definición del contexto de la consulta
contextConsulta:=DBMS_XMLQuery.newContext(’select * from clientes’);
-- obtener el resultado
resultado:= DBMS_XMLQuery.getXML(contextConsulta);
-- mostrar el resultado
mostrarCLOB(resultado);
Con el fin de facilitar la presentación de los elementos en formato CLOB, se ha escrito el método mostrarCLOB:
La ejecución de este script proporciona el siguiente resultado:
Por supuesto, el resultado es bastante satisfactorio, pero aún no constituye un documento XML utilizable tal cual.
b. Modificación de las etiquetas ROW y ROWSET
La API XSU para PL/SQL permite modificar el nombre de las etiquetas ROW y ROWSET. En nuestro ejemplo, la
Ahora el script para generar código XML será como sigue:
set serveroutput on
-- Dar formato XML al resultado de una consulta
declare
contextConsulta DBMS_XMLQuery.ctxType;
resultado CLOB;
begin
-- definición del contexto de la consulta
contextConsulta:=DBMS_XMLQuery.newContext(’select * from clientes’);
-- obtener el resultado
resultado:= DBMS_XMLQuery.getXML(contextConsulta);
-- mostrar el resultado
mostrarCLOB(resultado);
Y el resultado de la ejecución del script es el siguiente:
c. Limitación del número de filas
Las filas de datos extraídas a través de la consulta pueden incluirse en una página mediante los procedimientos
setMaxRows y setSkipRows. El procedimiento setMaxRows permite establecer el número máximo de filas de
datos que se convertirán a formato XML, mientras que el procedimiento setSkipRows permite especificar el
número de filas de datos que deben omitirse antes de comenzar la conversión al formato XML.
Estos procedimientos pueden utilizarse, por ejemplo, para limitar el número de filas de datos presentes en cada
documento XML.
El siguiente ejemplo permite limitar a 10 el número de clientes que se incluyen en cada documento XML generado. Con el fin
de que no se genere ninguna excepción después de tratar todas las filas, hay que llamar al método
setRaiseNoRowsException:
set serveroutput on
-- Dar formato XML al resultado de una consulta
declare
contextConsulta DBMS_XMLQuery.ctxType;
resultado CLOB;
begin
-- definición del contexto de la consulta
contextConsulta:=DBMS_XMLQuery.newContext(’select * from clientes’);
d. Hojas de estilo
La API XSU permite utilizar hojas de estilo en la generación de documentos XML.
El procedimiento setStyleSheetHeader() permite añadir la referencia a la hoja de estilos en la cabecera del
documento resultante.
El procedimiento useStyleSheet() permite aplicar la hoja de estilos directamente al documento resultante.
La segunda solución es mejor que la primera, ya que evita tener que volver a procesar el documento para aplicar
la hoja de estilos en un segundo paso.
2. Consultas parametrizadas
Después de crear el contexto, hay que proporcionar la consulta SQL que se utilizará para extraer los datos. Sin
embargo, esta consulta puede contener parámetros a los que se les asignará un valor justo antes de la ejecución
de la consulta. En efecto, la consulta solo se ejecuta cuando se solicita la construcción del documento XML final
mediante el método getXMLClob.
Durante la escritura de la consulta, las variables se consideran como variables externas y, por tanto, van precedidas
del signo de dos puntos (:).
El método setBindValue permite especificar el valor que tomará un parámetro. Lógicamente, es necesario
inicializar el conjunto de parámetros antes de solicitar la primera generación del documento XML. Sin embargo, entre
dos solicitudes de generación de documento, no es preciso reinicializar todos los parámetros, sino solamente
aquellos que hayan cambiado.
Ejemplo
El siguiente ejemplo ilustra la implementación de consultas parametrizadas para trabajar con la API XSU. Se generan dos
documentos XML, correspondiendo cada uno de ellos a un determinado cliente, pero solo se establece un contexto XSU, ya que
los datos proceden de la misma consulta, que dispone de un parámetro de restricción.
set serveroutput on
-- Dar formato XML al resultado de una consulta
declare
contextConsulta DBMS_XMLQuery.ctxType;
resultado CLOB;
begin
-- obtener el resultado
resultado:= DBMS_XMLQuery.getXML(contextConsulta);
-- mostrar el resultado
mostrarCLOB(resultado);
-- obtener el resultado
resultado:= DBMS_XMLQuery.getXML(contextConsulta);
-- mostrar el resultado
mostrarCLOB(resultado);
-- cierre del contexto de la consulta
DBMS_XMLQuery.closeContext(contextConsulta);
end;
/
3. Almacenamiento de datos en formato XML con DBMS_XMLSave
La API XSU para PL/SQL también incluye el paquete DBMS_XMLSave, el cual permite almacenar, en las tablas de la
base de datos, datos que inicialmente se encuentran en documentos con formato XML. Gracias a este segundo
paquete, XSU permite demostrar que XML es realmente un formato de intercambio de datos que puede utilizarse
para realizar transferencias de datos entre bases de datos.
Se pueden emplear los datos proporcionados en formato XML para realizar operaciones de inserción, actualización y
borrado (instrucciones INSERT, UPDATE o DELETE).
En general, todos los scripts PL/SQL que utilizan el paquete DBMS_XMLSave respetan la siguiente estructura:
l Creación de un contexto de ejecución mediante la función DBMS_XMLSave.getCtx. Esta función recibe como
parámetro el nombre de la tabla sobre la que se realizarán las operaciones de inserción (INSERT), borrado (DELETE)
o actualización (UPDATE).
l Si el documento XML se utiliza como soporte en la adición de datos (INSERT) a la tabla, es posible especificar las
columnas para las que se van a suministrar valores mediante la función setUpdateColNames. Por omisión, los valores
se proporcionan para todas las columnas de la tabla.
l Si el documento XML se emplea como soporte de una operación de actualización de datos (UPDATE), hay que
proporcionar la o las columnas que se van a utilizar, con el fin de identificar de forma exacta los datos que hay que
modificar. También se pueden especificar la o las columnas que se van a actualizar.
l Si el documento XML se emplea como soporte de una operación de borrado (DELETE), se pueden especificar la o las
columnas que se utilizarán con el fin de identificar de forma precisa los datos que hay que eliminar. Por omisión, todos
los datos del documento XML sirven para identificar los datos que se van a eliminar.
l Proporcionar un documento XML a uno de los métodos insertXML, updateXML o deleteXML para llevar a cabo la
operación deseada con el documento XML.
l Cerrar el contexto.
Para emplear los datos existentes en el documento XML con el fin de añadirlos a una tabla basta con especificar el
nombre de la tabla o vista, así como el documento XML. XSU se encarga de generar las instrucciones INSERT. Por
omisión, la instrucción INSERT afecta a todas las columnas de la tabla o vista y se emplea el valor NULL cuando no
se especifica otra cosa en el documento XML.
Ejemplo
El siguiente ejemplo ilustra el uso de la función insertXML:
-- añadir filas
numFilas:=DBMS_XMLSave.insertXML(contextAgregar, documentoXML);
-- cerrar el contexto
DBMS_XMLSave.closeContext(contextAgregar);
end;
/
El documento XML usado para agregar los datos es:
La llamada al procedimiento se realiza del siguiente modo:
-- establecer el directorio
create or replace directory "xml_dir" as ’C:\xml’;
dest_clob CLOB;
archivo_in BFILE;
vid number;
begin
archivo_in:= bfilename(’xml_dir’,’datos.xml’);
-- abrir el archivo
dbms_lob.fileopen(archivo_in, dbms_lob.file_readonly);
if (dbms_lob.fileexists(archivo_in)=1) then
-- cerrar el archivo
dbms_lob.fileclose(archivo_in);
end if;
end;
/
También se puede emplear este método de inserción para afectar solo a determinadas columnas de la tabla de
destino. En este caso, es preciso llamar al método setUpdateColumn para especificar el nombre de las
columnas que van a contener los valores que hay que insertar. Para eliminar cualquier riesgo de definir mal los
parámetros, el método clearUpdateColumnList permite eliminar toda referencia que se haya podido hacer a
las columnas anteriormente.
Ejemplo
El ejemplo siguiente lee los datos en formato XML almacenados en un archivo y después carga los datos en la tabla de
clientes:
begin
archivo_in:= bfilename(’xml_dir’,’datos2.xml’);
-- abrir el archivo
dbms_lob.fileopen(archivo_in, dbms_lob.file_readonly);
-- cerrar el archivo
dbms_lob.fileclose(archivo_in);
b. Actualización de datos
La actualización es una operación algo más delicada, ya que es necesario indicar la o las columnas que sirven para
identificar la fila, así como la o las columnas cuyos valores se van a actualizar.
Ejemplo
El siguiente ejemplo permite especificar la ciudad y el código postal de los clientes con números 200 y 201 (los clientes
añadidos en los ejemplos anteriores):
declare
-- variables necesarias para leer un archivo
documentoXML CLOB;
archivo_in BFILE;
tamaño number;
inicio_destino integer:=1;
inicio_origen integer:=1;
juego_caracteres number:=0;
contexto_idioma number:=0;
aviso number:=0;
begin
archivo_in:= bfilename(’xml_dir’,’datos3.xml’);
-- abrir el archivo
dbms_lob.fileopen(archivo_in, dbms_lob.file_readonly);
end;
/
El archivo XML que sirve de base para la actualización:
c. Borrado de los datos
Por último, se puede utilizar un documento XML para llevar a cabo el borrado de una serie de datos. Las columnas
existentes en el documento XML servirán para construir la cláusula WHERE. Se puede limitar el número de
columnas utilizadas para definir la restricción de filas llamando al procedimiento setKeyColumn.
El siguiente ejemplo permite borrar los clientes número 200 y 201. Esta información está almacenada en un archivo XML
denominado datos4.xml.
declare
-- variables necesarias para leer un archivo
documentoXML CLOB;
begin
archivo_in:= bfilename(’xml_dir’,’datos4.xml’);
-- abrir el archivo
dbms_lob.fileopen(archivo_in, dbms_lob.file_readonly);
end;
/
El uso del paquete DBMS_XMLSave es un tanto tedioso en lo que se refiere a la escritura de procedimientos,
especialmente en el nivel de inicialización del contexto. Dado que el contexto está relacionado con una tabla