Trabajando con datos masivos SQL Server, VFP, XML, Stored procedures.
Introducción
En el mundo de la gestión de bases de datos, la eficiencia y la rapidez en la manipulación de datos son cruciales. Una técnica que ha ganado popularidad por su capacidad para manejar grandes volúmenes de datos de manera eficiente es el uso de XML para la inserción y modificación masiva de registros en SQL Server. Esta metodología no solo optimiza el rendimiento, sino que también simplifica el proceso de actualización de múltiples registros, lo que resulta en una mejora significativa en la productividad y la precisión de las operaciones.
Las bondades de trabajar con XML para la inserción y modificación masiva de registros
Eficiencia en el manejo de datos masivos: Utilizar XML como parámetro permite enviar múltiples registros en una sola transacción. Esto reduce considerablemente el número de llamadas a la base de datos, minimizando el overhead asociado y acelerando el proceso de inserción o actualización de datos.
Simplificación del código y mantenimiento: Al agrupar los datos en un solo documento XML, el código SQL necesario para manejar estas operaciones se simplifica. En lugar de escribir múltiples sentencias de inserción o actualización, se puede procesar el XML con un solo bloque de código, facilitando el mantenimiento y la escalabilidad de la aplicación.
Reducción del tráfico de red: Al enviar un único documento XML que contiene todos los registros a insertar o actualizar, se disminuye significativamente el tráfico de red entre la aplicación y el servidor de bases de datos. Esto es especialmente beneficioso en entornos donde el ancho de banda es limitado o costoso.
Mejora en la integridad de los datos: Al realizar inserciones o actualizaciones masivas dentro de una transacción única, se asegura que todas las operaciones se realicen de manera atómica. Esto significa que, en caso de error, se puede revertir toda la transacción, manteniendo la integridad de los datos.
Flexibilidad y adaptabilidad: XML es un formato flexible que permite estructurar los datos de diversas maneras. Esto facilita la adaptación a diferentes tipos de esquemas de datos y permite manejar escenarios complejos sin necesidad de cambios significativos en la estructura de la base de datos.
Ejemplo:
En el ejemplo a presentar, veremos una entidad-relación de un sistema de ventas de manera simplificada, a fin de explicar las ventajas de insertar masivamente en un conjunto de tablas de bases coherentes y de alta integración. Utilizando algunos esquemas y relaciones, este sistema destaca por su capacidad para manejar grandes volúmenes de datos de manera eficiente y mantener la integridad de la información. Aquí, las principales bondades de este enfoque:
Entidad relación:
Principales Bondades
Organización Modular por Esquemas:
- Configuración: Agrupa tablas relacionadas con documentos, ubicaciones (Ubigeo), personas y monedas.
- Comercial: Administra listas de precios, áreas de venta, clientes, condiciones de venta y las ventas mismas.
- Producto: Maneja las unidades de manejo, familias de productos y los productos.
Integridad y Relaciones de Datos:
- Relaciones clave que aseguran la consistencia de los datos mediante claves foráneas, como las relaciones entre personas y sus ubicaciones (Ubigeo), y entre productos y sus familias.
- Uso de restricciones para mantener la coherencia y validez de los datos.
Jerarquías y Estructuras Flexibles:
- Soporte para estructuras jerárquicas en ubicaciones (Ubigeo) y familias de productos, permitiendo una representación clara y detallada de relaciones parentales y dependencias.
- Capacidad para asociar múltiples niveles de detalle en ventas, como áreas de venta y listas de precios.
Escalabilidad y Crecimiento:
- Diseño que facilita la expansión futura, permitiendo la incorporación de nuevos módulos o tablas sin afectar la integridad existente.
- Identificadores automáticos (IDENTITY) que simplifican la gestión de registros y evitan conflictos de datos.
Eficiencia en la Gestión de Clientes y Ventas:
- Administración integral de clientes, incluyendo detalles personales y relaciones con áreas de venta y listas de precios.
- Registro detallado de ventas y sus componentes, como productos, cantidades y condiciones de venta, optimizando el seguimiento y análisis de transacciones.
Manejo de Productos Completo:
- Gestión de productos a través de su identificación, clasificación por familias y unidades de manejo, y asignación de costos unitarios, facilitando el control de inventario y costos.
Script: Para recrear el escenario.
USE [master]
GO
Create database Sample01
go
use Sample01
go
Create schema Comercial
go
Create schema Configuracion
go
Create schema Producto
go
USE [MiDataEjemplo]
GO
CREATE TABLE [configuracion].[Tipo_Documento](
[Id_TipoDoc] [int] IDENTITY(1,1) NOT NULL,
[Nombre_TipoDoc]
[varchar](50) NULL,
CONSTRAINT
[PK_Tipo_Documento_1] PRIMARY KEY CLUSTERED
([Id_TipoDoc] ASC))
go
CREATE TABLE [configuracion].[Ubigeo](
[Id_Ubigeo]
[int] IDENTITY(1,1) NOT NULL,
[Nombre_Ubigeo] [varchar](100) NULL,
[Id_Ubigeo_Padre] [int] NULL,
CONSTRAINT [PK_Ubigeo] PRIMARY KEY CLUSTERED
([Id_Ubigeo] ASC))
ALTER TABLE [configuracion].[Ubigeo] WITH CHECK ADD CONSTRAINT [FK_Ubigeo_Ubigeo] FOREIGN KEY([Id_Ubigeo_Padre])
REFERENCES [configuracion].[Ubigeo] ([Id_Ubigeo])
GO
ALTER TABLE [configuracion].[Ubigeo] CHECK CONSTRAINT
[FK_Ubigeo_Ubigeo]
GO
CREATE TABLE [configuracion].[Persona](
[id_persona]
[int] IDENTITY(1,1) NOT NULL,
[Nombre_Persona] [varchar](50) NULL,
[Apellido_Paterno] [varchar](50) NULL,
[Apellido_Materno] [varchar](50) NULL,
[Id_Ubigeo] [int] NULL,
[Direccion] [varchar](254) NULL,
[Telefono] [char](10) NULL,
[Movil] [char](10) NULL,
[Email] [varchar](254) NULL,
[Id_TipoDoc] [int] NULL,
[Nro_doc]
[char](10) NULL,
CONSTRAINT
[PK_Persona] PRIMARY KEY CLUSTERED
([id_persona] ASC))
GO
ALTER TABLE [configuracion].[Persona] WITH CHECK ADD CONSTRAINT
[FK_Persona_Tipo_Documento] FOREIGN KEY([Id_TipoDoc])
REFERENCES [configuracion].[Tipo_Documento] ([Id_TipoDoc])
GO
ALTER TABLE [configuracion].[Persona] CHECK CONSTRAINT [FK_Persona_Tipo_Documento]
GO
ALTER TABLE [configuracion].[Persona] WITH CHECK ADD CONSTRAINT [FK_Persona_Ubigeo] FOREIGN KEY([Id_Ubigeo])
REFERENCES [configuracion].[Ubigeo] ([Id_Ubigeo])
GO
ALTER TABLE [configuracion].[Persona] CHECK CONSTRAINT [FK_Persona_Ubigeo]
GO
CREATE TABLE [configuracion].[Moneda](
[Id_Moneda]
[int] IDENTITY(1,1) NOT NULL,
[Nombre_Moneda] [varchar](30) NULL,
[Abrev_Moneda] [char](5) NULL,
CONSTRAINT [PK_Moneda] PRIMARY KEY CLUSTERED
([Id_Moneda] ASC))
GO
CREATE TABLE [comercial].[Lista_precios](
[Id_Lprecio] [int] IDENTITY(1,1) NOT NULL,
[Nombre_Lprecio]
[varchar](50) NULL,
[id_moneda]
[int] NOT NULL,
CONSTRAINT
[PK_Lista_precios] PRIMARY KEY CLUSTERED
([Id_Lprecio] ASC))
GO
CREATE TABLE [comercial].[Area_Venta](
[Id_Area]
[int] IDENTITY(1,1) NOT NULL,
[Nombre_Area]
[varchar](50) NULL,
CONSTRAINT
[PK_Area_Venta] PRIMARY KEY CLUSTERED
([Id_Area] ASC))
GO
CREATE TABLE [comercial].[Cliente](
[Id_Cliente]
[int] IDENTITY(1,1) NOT NULL,
[Id_Persona]
[int] NULL,
[Id_Area]
[int] NULL,
[Id_Lprecio]
[int] NULL,
CONSTRAINT
[PK_Cliente] PRIMARY KEY CLUSTERED
([Id_Cliente] ASC))
GO
ALTER TABLE [comercial].[Cliente] WITH CHECK ADD CONSTRAINT [FK_Cliente_Area_Venta] FOREIGN KEY([Id_Area])
REFERENCES [comercial].[Area_Venta] ([Id_Area])
GO
ALTER TABLE [comercial].[Cliente] CHECK CONSTRAINT [FK_Cliente_Area_Venta]
GO
ALTER TABLE [comercial].[Cliente] WITH CHECK ADD CONSTRAINT [FK_Cliente_Lista_precios] FOREIGN KEY([Id_Lprecio])
REFERENCES [comercial].[Lista_precios] ([Id_Lprecio])
GO
ALTER TABLE [comercial].[Cliente] CHECK CONSTRAINT [FK_Cliente_Lista_precios]
GO
ALTER TABLE [comercial].[Cliente] WITH CHECK ADD CONSTRAINT [FK_Cliente_Persona] FOREIGN KEY([Id_Persona])
REFERENCES [configuracion].[Persona] ([id_persona])
GO
ALTER TABLE [comercial].[Cliente] CHECK CONSTRAINT
[FK_Cliente_Persona]
GO
CREATE TABLE [comercial].[Condicion_Venta](
[Id_Cond_Venta]
[int] IDENTITY(1,1) NOT NULL,
[Nombre_Cond_Venta]
[varchar](50) NULL,
CONSTRAINT
[PK_Condicion_Venta] PRIMARY KEY CLUSTERED
([Id_Cond_Venta] ASC))
GO
CREATE TABLE [comercial].[Venta](
[Id_Venta]
[int] IDENTITY(1,1) NOT NULL,
[Id_Cliente]
[int] NOT NULL,
[Nro_Doc] [char](12) NULL,
[Fecha_Venta] [datetime] NULL,
[Obs_venta] [varchar](max) NULL,
[Id_Area] [int] NULL,
[Id_Moneda]
[int] NOT NULL,
[Id_Cond_Venta]
[int] NULL,
[id_lprecio]
[int] NULL,
CONSTRAINT [PK_Venta] PRIMARY KEY CLUSTERED
([Id_Venta] ASC))
GO
ALTER TABLE [comercial].[Venta] WITH CHECK ADD CONSTRAINT [FK_Venta_Area_Venta] FOREIGN KEY([Id_Area])
REFERENCES [comercial].[Area_Venta] ([Id_Area])
GO
ALTER TABLE [comercial].[Venta] CHECK CONSTRAINT
[FK_Venta_Area_Venta]
GO
ALTER TABLE [comercial].[Venta] WITH CHECK ADD CONSTRAINT [FK_Venta_Cliente] FOREIGN KEY([Id_Cliente])
REFERENCES [comercial].[Cliente] ([Id_Cliente])
GO
ALTER TABLE [comercial].[Venta] CHECK CONSTRAINT [FK_Venta_Cliente]
GO
ALTER TABLE [comercial].[Venta] WITH CHECK ADD CONSTRAINT [FK_Venta_Condicion_Venta] FOREIGN KEY([Id_Cond_Venta])
REFERENCES [comercial].[Condicion_Venta] ([Id_Cond_Venta])
GO
ALTER TABLE [comercial].[Venta] CHECK CONSTRAINT [FK_Venta_Condicion_Venta]
GO
ALTER TABLE [comercial].[Venta] WITH CHECK ADD CONSTRAINT [FK_Venta_Lista_precios] FOREIGN KEY([id_lprecio])
REFERENCES [comercial].[Lista_precios] ([Id_Lprecio])
GO
ALTER TABLE [comercial].[Venta] CHECK CONSTRAINT [FK_Venta_Lista_precios]
GO
ALTER TABLE [comercial].[Venta] WITH CHECK ADD CONSTRAINT [FK_Venta_Moneda] FOREIGN KEY([Id_Moneda])
REFERENCES [configuracion].[Moneda] ([Id_Moneda])
GO
ALTER TABLE [comercial].[Venta] CHECK CONSTRAINT [FK_Venta_Moneda]
GO
CREATE TABLE [producto].[Unidad_Manejo](
[Id_UM] [int] IDENTITY(1,1) NOT NULL,
[Nombre_UM] [varchar](10) NULL,
CONSTRAINT
[PK_Unidad_Manejo_1] PRIMARY KEY CLUSTERED
([Id_UM] ASC))
GO
CREATE TABLE [producto].[Familia_Producto](
[id_famprod] [int] IDENTITY(1,1) NOT NULL,
[id_famprod_padre]
[int] NULL,
[nombre_familia]
[varchar](100) NULL,
CONSTRAINT
[PK_Familia_Producto] PRIMARY KEY CLUSTERED
([id_famprod] ASC))
GO
ALTER TABLE [producto].[Familia_Producto] WITH CHECK ADD CONSTRAINT [FK_Familia_Producto_Familia_Producto] FOREIGN KEY([id_famprod_padre])
REFERENCES [producto].[Familia_Producto] ([id_famprod])
GO
ALTER TABLE [producto].[Familia_Producto] CHECK CONSTRAINT [FK_Familia_Producto_Familia_Producto]
GO
CREATE TABLE [producto].[Producto](
[id_producto] [int] IDENTITY(1,1) NOT NULL,
[Nombre_Producto] [varchar](150) NULL,
[id_famprod] [int] NULL,
[Id_UM] [int] NULL,
[costo_unitario] [numeric](12, 2) NULL,
CONSTRAINT [PK_Producto] PRIMARY KEY CLUSTERED
([id_producto] ASC))
GO
ALTER TABLE [producto].[Producto] WITH CHECK ADD CONSTRAINT [FK_Producto_Familia_Producto] FOREIGN KEY([id_famprod])
REFERENCES [producto].[Familia_Producto] ([id_famprod])
GO
ALTER TABLE [producto].[Producto] CHECK CONSTRAINT [FK_Producto_Familia_Producto]
GO
ALTER TABLE [producto].[Producto] WITH CHECK ADD CONSTRAINT [FK_Producto_Unidad_Manejo] FOREIGN KEY([Id_UM])
REFERENCES [producto].[Unidad_Manejo] ([Id_UM])
GO
ALTER TABLE [producto].[Producto] CHECK CONSTRAINT [FK_Producto_Unidad_Manejo]
GO
CREATE TABLE [comercial].[Venta_Detalle](
[id_ventad] [int] IDENTITY(1,1) NOT NULL,
[id_Venta]
[int] NOT NULL,
[id_producto]
[int] NOT NULL,
[Cantidad] [numeric](12, 3) NULL,
[Precio_unitario] [numeric](12, 2) NULL,
[Impuesto] [numeric](18, 6) NULL,
[Tcambio] [numeric](12, 3) NULL,
CONSTRAINT [PK_Venta_Detalle] PRIMARY KEY CLUSTERED
([id_ventad] ASC))
GO
ALTER TABLE [comercial].[Venta_Detalle] WITH CHECK ADD CONSTRAINT [FK_Venta_Detalle_Producto] FOREIGN KEY([id_producto])
REFERENCES [producto].[Producto] ([id_producto])
GO
ALTER TABLE [comercial].[Venta_Detalle] CHECK CONSTRAINT [FK_Venta_Detalle_Producto]
GO
ALTER TABLE [comercial].[Venta_Detalle] WITH CHECK ADD CONSTRAINT [FK_Venta_Detalle_Venta] FOREIGN KEY([id_Venta])
REFERENCES [comercial].[Venta] ([Id_Venta])
GO
ALTER TABLE [comercial].[Venta_Detalle] CHECK CONSTRAINT [FK_Venta_Detalle_Venta]
GO
Creando Nuestro Pimer Stored Procedure: Con este Query, recuperaremos una venta con su respectivo detalle.
create procedure comercial.select_venta
@id_venta int
as
SELECT [Id_Venta]
,[Id_Cliente]
,[Nro_Doc]
,[Fecha_Venta]
,[Obs_venta]
,[Id_Area]
,[Id_Moneda]
,[Id_Cond_Venta]
,[id_lprecio]
FROM [Comercial].[Venta] where id_venta=@id_Venta
SELECT [id_ventad]
,[id_Venta]
,[id_producto]
,[Cantidad]
,[Precio_unitario]
,[Impuesto]
,[Tcambio]
FROM [Comercial].[Venta_Detalle] where id_venta=@id_Venta
GO
grant execute on comercial.select_venta to public
Creamos la conexión a la base de datos
ncon=SQLSTRINGCONNECT("Driver=SQL Server;Server=5CG13128K2;Database=sample01")
Ejecutamos el Stored Procedure
=SQLEXEC(ncon,"execute comercial.select_venta 1","venta")
Poblando datos a las tablas
INSERT INTO [configuracion].[Tipo_Documento] ([Nombre_TipoDoc]) VALUES
('DNI'), ('RUC'), ('Pasaporte'), ('Carnet de Extranjería'),
('Licencia de Conducir'), ('Otro Tipo 1'), ('Otro Tipo 2'),
('Otro Tipo 3'), ('Otro Tipo 4'), ('Otro Tipo 5');
INSERT INTO [configuracion].[Ubigeo] ([Nombre_Ubigeo], [Id_Ubigeo_Padre]) VALUES
('Perú', NULL),
('Lima', 1),
('Arequipa', 1),
('Cusco', 1),
('La Libertad', 1),
('Trujillo', 4),
('Chiclayo', 4),
('Piura', 4),
('Ica', 1),
('Tacna', 1);
INSERT INTO [configuracion].[Moneda] ([Nombre_Moneda], [Abrev_Moneda]) VALUES
('Nuevo Sol', 'PEN'),
('Dólar Americano', 'USD'),
('Euro', 'EUR'),
('Libra Esterlina', 'GBP'),
('Yen Japonés', 'JPY'),
('Franco Suizo', 'CHF'),
('Dólar Canadiense', 'CAD'),
('Dólar Australiano', 'AUD'),
('Real Brasileño', 'BRL'),
('Peso Mexicano', 'MXN');
INSERT INTO [configuracion].[Persona] ([Nombre_Persona], [Apellido_Paterno], [Apellido_Materno], [Id_Ubigeo], [Direccion], [Telefono], [Movil], [Email], [Id_TipoDoc], [Nro_doc]) VALUES
('Juan', 'Perez', 'Lopez', 2, 'Av. Siempre Viva 123', '0123456789', '0987654321', 'juan.perez@example.com', 1, '12345678'),
('Maria', 'Garcia', 'Sanchez', 2, 'Calle Falsa 456', '0234567890', '0897654321', 'maria.garcia@example.com', 2, '87654321'),
('Carlos', 'Rodriguez', 'Martinez', 3, 'Jiron Peru 789', '0345678901', '0796543210', 'carlos.rodriguez@example.com', 3, '34567890'),
('Ana', 'Fernandez', 'Gomez', 4, 'Pasaje Libertad 101', '0456789012', '0695432109', 'ana.fernandez@example.com', 4, '45678901'),
('Luis', 'Lopez', 'Diaz', 5, 'Plaza Mayor 202', '0567890123', '0594321098', 'luis.lopez@example.com', 5, '56789012'),
('Jose', 'Martinez', 'Perez', 6, 'Calle Real 303', '0678901234', '0493210987', 'jose.martinez@example.com', 6, '67890123'),
('Laura', 'Sanchez', 'Ramirez', 7, 'Av. Principal 404', '0789012345', '0392109876', 'laura.sanchez@example.com', 1, '78901234'),
('David', 'Ramirez', 'Vega', 8, 'Jiron Central 505', '0890123456', '0291098765', 'david.ramirez@example.com', 2, '89012345'),
('Elena', 'Gomez', 'Flores', 9, 'Pasaje Secundario 606', '0901234567', '0190987654', 'elena.gomez@example.com', 3, '90123456'),
('Jorge', 'Vega', 'Morales', 10, 'Calle Tercera 707', '1012345678', '0089876543', 'jorge.vega@example.com', 4, '01234567');
INSERT INTO [comercial].[Lista_precios] ([Nombre_Lprecio], [id_moneda]) VALUES
('Lista General', 1),
('Lista Promocional', 1),
('Lista Especial', 1),
('Lista VIP', 1),
('Lista Descuento', 1),
('Lista Exportación', 2),
('Lista Importación', 3),
('Lista Local', 4),
('Lista Nacional', 5),
('Lista Internacional', 6);
INSERT INTO [comercial].[Area_Venta] ([Nombre_Area]) VALUES
('Area Norte'),
('Area Sur'),
('Area Este'),
('Area Oeste'),
('Area Centro'),
('Area Lima'),
('Area Provincias'),
('Area Internacional'),
('Area Online'),
('Area Directa');
INSERT INTO [comercial].[Cliente] ([Id_Persona], [Id_Area], [Id_Lprecio]) VALUES
(1, 1, 1),
(2, 2, 2),
(3, 3, 3),
(4, 4, 4),
(5, 5, 5),
(6, 6, 6),
(7, 7, 7),
(8, 8, 8),
(9, 9, 9),
(10, 10, 10);
INSERT INTO [comercial].[Condicion_Venta] ([Nombre_Cond_Venta]) VALUES
('Contado'),
('Crédito 30 días'),
('Crédito 60 días'),
('Crédito 90 días'),
('Cheque'),
('Transferencia Bancaria'),
('Tarjeta de Crédito'),
('PayPal'),
('Efectivo'),
('Otro');
INSERT INTO [comercial].[Venta] ([Id_Cliente], [Nro_Doc], [Fecha_Venta], [Obs_venta], [Id_Area], [Id_Moneda], [Id_Cond_Venta], [id_lprecio]) VALUES
(1, '001-0001', '2024-01-01', 'Observación 1', 1, 1, 1, 1),
(2, '001-0002', '2024-01-02', 'Observación 2', 2, 2, 2, 2),
(3, '001-0003', '2024-01-03', 'Observación 3', 3, 3, 3, 3),
(4, '001-0004', '2024-01-04', 'Observación 4', 4, 4, 4, 4),
(5, '001-0005', '2024-01-05', 'Observación 5', 5, 5, 5, 5),
(6, '001-0006', '2024-01-06', 'Observación 6', 6, 6, 6, 6),
(7, '001-0007', '2024-01-07', 'Observación 7', 7, 7, 7, 7),
(8, '001-0008', '2024-01-08', 'Observación 8', 8, 8, 8, 8),
(9, '001-0009', '2024-01-09', 'Observación 9', 9, 9, 9, 9),
(10, '001-0010', '2024-01-10', 'Observación 10', 10, 10, 10, 10);
INSERT INTO [producto].[Unidad_Manejo] ([Nombre_UM]) VALUES
('Unidad'),
('Caja'),
('Paquete'),
('Tonelada'),
('Gramo'),
('Kilogramo'),
('Metro'),
('Litro'),
('Botella'),
('Lata');
INSERT INTO [producto].[Familia_Producto] ([id_famprod_padre], [nombre_familia]) VALUES
(NULL, 'Electrónicos'),
(1, 'Televisores'),
(1, 'Computadoras'),
(1, 'Smartphones'),
(NULL, 'Muebles'),
(5, 'Sillas'),
(5, 'Mesas'),
(NULL, 'Ropa'),
(8, 'Hombres'),
(8, 'Mujeres');
INSERT INTO [producto].[Producto] ([Id_Famprod], [Nombre_Producto], [Id_UM], [costo_unitario]) VALUES
(2, 'Televisor 32 pulgadas', 1, 1),
(2, 'Televisor 40 pulgadas', 1, 1),
(3, 'Laptop 14 pulgadas', 1, 1),
(3, 'PC de Escritorio', 1, 1),
(4, 'Smartphone 64GB', 1, 1),
(4, 'Smartphone 128GB', 1, 1),
(6, 'Silla de Oficina', 1, 1),
(7, 'Mesa de Comedor', 1, 1),
(9, 'Camisa Hombre', 1, 1),
(10, 'Blusa Mujer', 1, 1);
INSERT INTO [comercial].[Venta_Detalle] ([Id_Venta], [Id_Producto], [Cantidad], [Precio_unitario], tcambio) VALUES
(1, 1, 2, 1000.00, 1),
(2, 2, 1, 1200.00, 1),
(3, 3, 1, 1500.00, 1),
(4, 4, 3, 800.00, 1),
(5, 5, 2, 600.00, 1),
(6, 6, 1, 700.00, 1),
(7, 7, 5, 200.00, 1),
(8, 8, 1, 500.00, 1),
(9, 9, 4, 100.00, 1),
(10, 10, 3, 120.00, 1);
SQL Server, Stored Procedure de Inserción másiva.
create procedure [comercial].[venta_inserta_xml]
@id_venta int output,
@id_cliente int,
@nro_doc char(12),
@fecha_Venta datetime,
@obs_venta varchar(max),
@id_Area int,
@id_moneda int,
@id_cond_venta int,
@id_lprecio int,
@xmldetalle xml
as
declare @id_producto int , @Cantidad numeric(12,3),
@Precio_unitario numeric(12,2), @Impuesto numeric(18,6),@Tcambio numeric(12,3),@id_ventad int
begin try
begin tran
if @id_venta=0
begin
insert into comercial.Venta (Id_Cliente,Nro_Doc,Fecha_Venta,Obs_venta,Id_Area,Id_Moneda,Id_Cond_Venta,id_lprecio)
values (@id_cliente,@nro_doc,@fecha_Venta,@obs_venta,@id_Area,@id_moneda,@id_cond_venta,@id_lprecio)
set @id_Venta = (SELECT IDENT_CURRENT ('comercial.Venta'))
end
else
begin
update comercial.Venta set id_cliente=@id_cliente, nro_doc=@nro_doc, fecha_Venta=@fecha_Venta, obs_venta=@obs_venta,
id_Area=@id_Area, id_moneda=@id_moneda,
id_cond_venta=@id_cond_venta, @id_lprecio=@id_lprecio
where id_venta=@id_venta
end
insert into comercial.Venta_Detalle (id_venta,id_producto,Cantidad,Precio_unitario,Impuesto,Tcambio)
select @id_venta,
id_producto=(ItmCnp.Item.value('@id_producto','int')),
cantidad=(ItmCnp.Item.value('@cantidad','numeric(12,3)')),
precio_unitario=(ItmCnp.Item.value('@precio_unitario','numeric(12,2)')),
impuesto=(ItmCnp.Item.value('@impuesto','numeric(18,6)')),
tcambio=(ItmCnp.Item.value('@tcambio','numeric(12,3)'))
from @xmldetalle.nodes('ROOT/venta1') as ItmCnp(Item) where ItmCnp.Item.value('@id_ventad', 'int')=0
UPDATE comercial.Venta_Detalle SET
Venta_Detalle.Cantidad = ItmCnp.Item.value('@cantidad', 'numeric(12,3)'),
Venta_Detalle.Precio_unitario = ItmCnp.Item.value('@precio_unitario', 'numeric(12,2)'),
Venta_Detalle.Impuesto = ItmCnp.Item.value('@impuesto', 'numeric(18,6)'),
Venta_Detalle.Tcambio = ItmCnp.Item.value('@tcambio', 'numeric(12,3)')
FROM comercial.Venta_Detalle
INNER JOIN @xmldetalle.nodes('ROOT/venta1') AS ItmCnp(Item)
ON
Venta_Detalle.id_ventad = ItmCnp.Item.value('@id_ventad', 'int') where ItmCnp.Item.value('@id_ventad', 'int')<>0
commit tran
end try
begin catch
ROLLBACK TRANSACTION
DECLARE
@ErrorMessage NVARCHAR(4000),@ErrorSeverity INT,@ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE()
RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState)
end catch
go
grant execute on [comercial].[venta_inserta_xml]
to public
go
VFP PRG, Para generar de cursor a XML
Sintaxis:
_mixml = creaxml("Cursor")
LPARAMETERS
tcAlias as String, tlClosealias as Logical
LOCAL XMLResult as String , oError as Exception
XMLResult=''
LcCabecera = "<?xml version="
+ Chr(34) + "1.0" + Chr(34) +;
" encoding=" + Chr(34) + "iso-8859-1" + Chr(34) + "?>"
XMLBody=''
SELECT(tcAlias)
LnColum = FCOUNT()
GO top
SCAN
XMLBody = XMLBody+' <'+tcAlias
FOR lncol=1 TO LnColum
LcNameField = LOWER(FIELD(lncol))
LvValor = &LcNameField
LcValor=''
DO Case
CASE VARTYPE(LvValor)='D'
LcValor = DTOC(LvValor)
CASE VARTYPE(LvValor)='T'
LcValor = TTOC(LvValor,3)
CASE VARTYPE(LvValor)='N' && Numerico
LcValor = ALLTRIM(TRANSFORM(LvValor))
CASE VARTYPE(LvValor)='X' && NUll
DO Case
CASE TYPE('LvValor')='N'
LcValor = "0"
CASE TYPE('LvValor')='D' OR TYPE('LvValor')='T'
LcValor =
'01/01/1900'
CASE TYPE('LvValor')='C'
LcValor = ' '
ENDCASE
CASE VARTYPE(LvValor)='L' && Logico
LcValor = ICASE(LvValor,'1','0')
OTHERWISE
LcValor = ALLTRIM(LvValor)
ENDCASE
XMLBody=XMLBody+'
'+LcNameField+'='+CHR(34)+LcValor+CHR(34)
ENDFOR
XMLBody=XMLBody+'></'+tcAlias+'>'
ENDSCAN
XMLResult=LcCabecera + '<ROOT>'+;
XMLBody+;
'</ROOT>'
IF tlClosealias=.t.
endif
RETURN XMLResult
Llenando variables y Generando XML
=SQLEXEC(ncon,"execute
comercial.select_venta 1","venta")
Actualizando datos en la cabecera y adiconando registros al detalleActualizando variables, generando XML y ejecutando Stored Procedure.
SELECT venta
SCATTER MEMVAR memo
SELECT venta1
_mixml = creaxml("venta1")
=SQLEXEC(ncon,"comercial.venta_inserta_xml
?@m.id_venta,?m.id_cliente,?m.nro_doc,?m.fecha_Venta,?m.obs_venta,?m.id_Area,?m.id_moneda,?m.id_cond_venta,?m.id_lprecio,?_mixml")
USE IN venta
USE IN venta1
=SQLEXEC(ncon,"execute comercial.select_venta 1","venta")
Validando en SQL Server
select * from comercial.venta where id_venta=1
select * from comercial.venta_detalle
where id_venta=1
Conclusión
En resumen, la utilización de XML para la inserción y modificación masiva de registros en SQL Server es una estrategia poderosa que mejora la eficiencia, simplifica el mantenimiento, reduce el tráfico de red, mejora la integridad de los datos y ofrece una gran flexibilidad. Adoptar esta técnica puede transformar significativamente la forma en que se gestionan los datos en cualquier organización, contribuyendo a una mayor agilidad y precisión en las operaciones de bases de datos.
Gracias por tu tiempo. Sólo tengo una duda. ¿Por qué crear una función que arme el XML "manualmente" cuando se puede usar la función CURSORTOXML() o la clase XMLAdapter que es más fácil de programar y ejecuta más rápido? Yo he usado la función CURSORTOXML() y me ha funcionado muy bien.
ResponderEliminar¡Hola Skysurfer1967!
EliminarHe creado un programa (PRG) que genera un archivo XML más simplificado que el que proporciona la función cursortoxml(), con el fin de ofrecer una opción adicional . Este enfoque puede ser útil si buscas una estructura XML más sencilla y específica para tus datos.
¡Espero que te sea de ayuda!
Saludos,