mayo 23, 2006

Uso de XML con SQL Server 2000 para operaciones que requieren transacciones con n registros

En algún momento que leía un libro de SQL Server 2000 me sorprendió encontrar una forma de utilizar XML con SQL Server 2000 para poder insertar n registros en una sola operación -también llamada transacción-. Para poder lograr esto SQL Server 2000 cuenta con un procedimiento almacenado llamado: "sp_xml_preparedocument" que es el encargado de leer la cadena con formato XML y cargarla en la memoria para poder recorrerla.

A continuación expongo un ejemplo del caso de la inserción de un objeto Factura en la Base de Datos utilizando XML. Como todos sabemos una factura se compone de dos conceptos: un encabezado y un detalle, el encabezado es el que expone datos del cliente, la fecha y otros, estos datos conforman un registro o renglón en la Base da datos y se inserta en una tabla llamada Factura. El siguiente concepto u apartado que conforman a una factura es el Detalle, éste contiene a todos los registros o renglones de los conceptos que se están facturando al cliente y que pueden ser uno o más (ver figura del modelo Entidad/Relación) y aquí es en donde XML viene a facilitarnos la vida para poder insertar los dos objetos -el encabezado y el detalle- en una sola operación.











La solución se expone como un store procedure que recibe los datos que componen al encabezado y la cadena XML que compone a los del detalle, así que la única condición para que sp_xml_preparedocument pueda leer la cadena XML es que ésta sea válida.

Espero que les sea de mucha utilidad, porque casi que yo siempre la utilizó en los proyectos que desarrollo, pues el patrón maestro-detalle por lo regular siempre está presente de alguna forma en todo proyecto.

----------------------------------------------------------------------------
/*
Este procedimiento almancenado inserta un Encabezado-Detalle de una Factura.
El Detalle se pasa como una cadena XML con la siguiente estructura:

*/

CREATE PROCEDURE dbo.spInsertXMLEncDetFactura
(
@IdCte int,
@FechaFactura datetime,
@IVA numeric(8,2),
@SubTotal numeric(8,2),
@xmlDetFactura varchar(8000)--o tipo Text -Cadena XML con el detalle de la factura.
)
AS

DECLARE @idoc int --xmlDoc
DECLARE @IdFactura int --Nueva Folio Factura

--Ejecutar el sp que carga en memoria el docuemnto XML.
EXEC sp_xml_preparedocument @idoc output, @xmlDetFactura

--SET NOCOUNT ON
DECLARE @CurrentError int

--Comienza la transacción
BEGIN TRANSACTION
--Agregar el encabezado de la factura.

INSERT INTO FACTURA
(IdCte, FechaFactura, IVA, SubTotal)
VALUES (@IdCte, @FechaFactura, @IVA, @SubTotal);

--Verificar si hubo errores
SELECT @CurrentError = @@Error
IF @CurrentError != 0
GOTO ERROR_HANDLER


--Obtener el nuevo Identity de la tabla FACTURA.
SELECT @IdFactura = @@IDENTITY

--Agregar conceptos de FACTURA a la tabla DET_FACTURA.
INSERT INTO DET_FACTURA (IdFactura, IdProducto, CantidadProducto, PrecioProductoVta)
SELECT @IdFactura, IdProducto, CantidadProducto, PrecioProductoVta
FROM OPENXML (@idoc, '/DetFactura/Concepto')
WITH DET_FACTURA

--Verificar si hubo errores
SELECT @CurrentError = @@Error
IF @CurrentError != 0
GOTO ERROR_HANDLER


--Finalizar la Transacción
COMMIT TRANSACTION
SET NOCOUNT OFF

--Descargar documento XML de la memoria.
EXEC sp_xml_removedocument @idoc
--Retornar el nuevo No. de Solcitud de Compra.
RETURN @IdFactura

--Manejador de Error.
ERROR_HANDLER:
ROLLBACK TRANSACTION
--Descargar documento XML de la memoria.
EXEC sp_xml_removedocument @idoc
SET NOCOUNT OFF
RETURN 0
GO

No hay comentarios.: