jueves, diciembre 5, 2019

Usando MERGE para INSERT y UPDATE

Que es lo que se hace cuando en una aplicación requerimos agregar un registro nuevo, pero si este ya existe modificarlo con los nuevos datos. Si estas utilizando SQL Server 2005 o inferior debes escribir 2 o 3 querys, uno para verificar si el registro existe, si existe entonces actualizas y si no existe lo insertas.  En SQL Server 2008 se han hecho cambios para mejorar esto y ahora en una sola sentencia puedes hacer esto, insert o update usando la instrucción MERGE.

La instrucción MERGE básicamente une datos de un resultado de origen establecido en una tabla destino. Se envían los datos al MERGE, el los compara (por la llave primaria), si existe los actualiza y si no existe los ingresa, también podría ser que si no cumple con los requisitos los pueda borrar,  insert, update y delete en una sola instrucción.

MERGE también permite comparar dos tablas, una fuente y otra destino en ingresar o modificar los datos de la tabla en base a los datos de otra tabla, eso lo veremos en otro ejemplo que publicaremos en este sitio.

En este primer ejemplo sobre MERGE vamos a hacer el manejo típico de datos en una tabla, insert y update.

Tabla que vamos a utilizar de ejemplo.

CREATE TABLE [dbo].[tablaPrueba](
    [id] [int] NOT NULL,
    [nombre] [varchar](50) NULL,
    [fecha_ingreso] [datetime] NULL,
    [fecha_actualizacion] [datetime] NULL,
 CONSTRAINT [PK_tablaPrueba] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)

Primero vamos a mostrar como se hace o hacia normalmente en SQL, principalmente si se utiliza SQL 2005 o inferior.

-- Ejemplo 1 obsoleto pero funcional en SQL 2008 o superior
CREATE PROCEDURE InsertaTablaPrueba(
@id int,
@nombre varchar(50) 
)
AS
BEGIN
    SET NOCOUNT ON
 
    --Se actualizan los registros en la tabla
    UPDATE tablaPrueba
       SET nombre = @nombre,
           fecha_actualizacion = GETDATE()
     WHERE id = @id
     --Si no se actualizó ningún registro se inserta en la tabla
     IF (@@ROWCOUNT = 0 )
     BEGIN
        INSERT INTO tablaPrueba (id, nombre, fecha_ingreso, fecha_actualizacion)
        VALUES(@id, @nombre, GETDATE(), GETDATE())
     END
END

En ese ejemplo podemos ver que se solicitar modificar un registro y si este no afectó ningún registro (@@ROWCOUNT=0) lo actualiza. En el peor de los casos se ejecutan dos querys, se toca dos veces la tabla.

-- Ejemplo 2, obsoleto pero funcional en SQL 2008 o superior
CREATE PROCEDURE InsertaTablaPrueba2(
@id int,
@nombre varchar(50) 
)
AS
BEGIN
    SET NOCOUNT ON
 
    IF EXISTS(SELECT 1 FROM tablaPrueba
               WHERE id = @id)
    BEGIN
        --Se actualizan los registros en la tabla
        UPDATE tablaPrueba
           SET nombre = @nombre,
               fecha_actualizacion = GETDATE()
         WHERE id = @id
     END
     ELSE
     BEGIN
        --Si no existe el registro se inserta en la tabla
        INSERT INTO tablaPrueba (id, nombre, fecha_ingreso, fecha_actualizacion)
        VALUES(@id, @nombre, GETDATE(), GETDATE())
     END
 
END

En este ejemplo se consulta si el registro existe, y luego se actualiza o se inserta, siempre se toca 2 veces la tabla.

Ahora en el siguiente ejemplo vamos a utilizar MERGE, vamos a ver como en una sola sentencia se inserta o actualiza un registro, mucho más eficiente.

-- Ejemplo 3, usando MERGE, mucho más eficiente
CREATE PROCEDURE InsertaTablaPruebaMerge(
@id int,
@nombre varchar(50) 
)
AS
BEGIN
    SET NOCOUNT ON
 
    MERGE tablaPrueba as TARGET
    USING(SELECT @id, @nombre) AS SOURCE(id, nombre)
    ON (TARGET.id = SOURCE.id)
    WHEN MATCHED THEN
        UPDATE SET nombre = SOURCE.nombre, 
                   fecha_actualizacion = GETDATE()
    WHEN NOT MATCHED THEN
        INSERT (id, nombre, fecha_ingreso, fecha_actualizacion)
        VALUES (SOURCE.id, SOURCE.nombre, GETDATE(), GETDATE());
END

Podemos ver que MERGE recibe una tabla destino, que es a la que se le van a ingresar o modificar los datos (TARGET), luego recibe la tabla fuente o los datos fuente, en este caso son datos fuente (SOURCE). Luego de estos, cuando los datos concuerdan (WHEN MATCHED) realiza el UPDATE en la tabla, y cuando no existen los registros (WHEN NOT MATCHED) realiza el INSERT

Datos para probar los 3 procedimientos

EXEC InsertaTablaPrueba 1, 'Valor núm. 1'
EXEC InsertaTablaPrueba 2, 'Valor núm. 2'
EXEC InsertaTablaPrueba 3, 'Valor núm. 3'
EXEC InsertaTablaPrueba 4, 'Valor núm. 4'
 
EXEC InsertaTablaPrueba2 4, 'Valor núm. 4.1'
 
EXEC InsertaTablaPruebaMerge 5, 'Valor núm. 5'
EXEC InsertaTablaPruebaMerge 3, 'Valor núm. 3.1'
 
EXEC InsertaTablaPruebaMerge 6, 'Valor núm. 6'
EXEC InsertaTablaPrueba 2, 'Valor núm. 2.1'
 
SELECT * FROM tablaPrueba

 




Roy Rojashttp://www.dotnetcr.com
Con más de 20 años de experiencia en programación, experto en lenguajes .NET, VB, C#, ASP.NET, Xamarin, XCode, DBA en SQL Server. Creador de dotnetcr.com, sitio web para programadores en español. royrojas.com | dotnetcr.com | GitHub

Redes Sociales

2,785FansMe gusta
337SeguidoresSeguir

Popular esta semana

Llamar funciones JavaScript desde el code-behind en ASP.NET

Explicamos como llamar métodos o funciones de JavaScript en nuestras aplicaciones en ASP.NET, eventos de botones o desde el code-behind.
ERROR PHP 7.2

Error: PHP Warning: count(): Parameter must be an array or an object that implements...

Como solucionar el error "PHP Warning: count() : Parameter must be an array or an object that implements Countable in..."

DELETE con subconsulta o INNER JOIN

En el siguiente ejemplo se explica la forma en que se pueden eliminar registros en nuestras tablas con instrucciones DELETE más complejas que las...

Últimos artículos

Ejemplos de Documentos Electrónicos 4.3

En este artículo vamos a brindar varios ejemplos de documentos electrónicos para la versión 4.3 de Factura Electrónica de Costa Rica.
Factura Electrónica Costa Rica

Encabezados del XML Factura Electrónica Costa Rica 4.3

Para generar el XML de la factura electrónica de Costa Rica se debe de seguir un formato específico para que estas sean...
C# - PDF417

Crear código PDF417 con iTextSharp y XZing en C# .NET

Para crear códigos PDF417 existen herramientas que podemos agregar a nuestra aplicaciones. En este ejemplo vamos explicar como utilizar iTextSharp y ZXing.

SQL Server: Error 3414, servicio no inicia

El error 3414 se produce generalmente cuando el motor de la base de datos SQL Server sufre algún evento imprevisto. Aquí lo solucionamos.