sql >> Base de Datos >  >> RDS >> Database

MERGE:actualización de tablas de origen y destino ubicadas en servidores separados

¿Qué es la instrucción MERGE?

Usando la declaración MERGE, podemos cambiar los datos en una tabla de destino en función de los datos en una tabla de origen. Usándolo, podemos ejecutar INSERTAR, ACTUALIZAR y ELIMINAR en las tablas de destino dentro de un solo bloque de consulta. Une ambas tablas mediante columnas, comunes en ambas tablas como la clave principal. Según cómo coincidan los datos de la columna, los cambios se aplican a los datos de la tabla de destino. La siguiente imagen ilustra cómo funciona "MERGE":

Con MERGE, podemos mejorar el rendimiento porque las tres operaciones (INSERTAR, ACTUALIZAR y ELIMINAR ) se realizan en un solo paso. No necesitamos escribir una declaración individual para actualizar los cambios en la tabla de destino.

La declaración de combinación utiliza SourceTable y tabla de destinos. Modifica DestinationTable basado en los datos de SourceTable . Ambas tablas se comparan utilizando la condición, definida en la instrucción Merge. Esta condición determina cómo SourceTable coincide con la tabla de destino. Es como condiciones de combinación que se utilizan para hacer coincidir filas.

Por lo general, la coincidencia debe realizarse mediante la coincidencia de identificadores únicos como claves principales. Por ejemplo, la tabla de origen es NewProduct y el destino es Productmaster y la clave principal es ProductID , la condición de fusión debería ser la siguiente:

NewProduct.ProductID=ProductMaster.ProdID

El siguiente es el formato de la sentencia MERGE:

MERGE target t
Using source s
ON joinCondition
WHEN MATCHED
THEN updateQuery
WHEN NOT MATCHED BY TARGET
THEN insertQuery
WHEN NOT MATCHED BY SOURCE
THEN deleteQuery

Para modificar los datos en la tabla de destino, MERGE admite las siguientes cláusulas T-SQL.

  1. CUANDO SE EMPAREJAN
  2. CUANDO NO COINCIDE [POR OBJETIVO]
  3. CUANDO NO COINCIDE [POR FUENTE]

Cláusula "CUANDO SE COINCIDE"

Esta cláusula se utilizará cuando queramos actualizar o eliminar los registros en la tabla de destino. Aquí los registros se consideran coincidentes cuando los datos dentro de las columnas unidas son los mismos.

Cláusula "CUANDO NO COINCIDE [POR OBJETIVO]"

Si el registro está presente en la tabla de origen pero no en la tabla de destino, esta cláusula se utilizará para insertar un nuevo registro en la tabla de destino.

Cláusula "CUANDO NO COINCIDE [POR FUENTE]"

Esta cláusula se utilizará cuando queramos eliminar o actualizar un registro en una tabla de origen que no coincide con una fila en la tabla de destino.

Utilice MERGE cuando el origen y el destino están en un servidor separado

En este artículo, voy a demostrar cómo realizar operaciones de inserción, actualización y eliminación mediante MERGE, cuando las tablas de origen y de destino están en servidores separados. Por ejemplo, una empresa farmacéutica utiliza software de inventario. Las bases de datos maestras de un software y las bases de datos transaccionales de software están en servidores de bases de datos separados. La siguiente es una configuración:

La compañía ha agregado algunos productos ordenados. Quiero realizar algunos procesos de limpieza mientras actualizo el stock de productos. A continuación se muestra la lista de tareas que se deben realizar.

  1. Si existe un producto en el inventario y se ordenó el mismo producto, actualice y luego actualice el stock.
  2. Si un producto no existe en el inventario y se ordena agregar un producto, agregue el producto en stock.
  3. Si el producto existe en el inventario pero no se pide y además el stock del producto no se actualiza durante más de un año, elimine el producto del inventario.

Para realizar la tarea antes mencionada, realizaremos los siguientes pasos:

  1. Cree una tabla temporal global llamada ##Source_Trn_Tabl mi. Rellene los datos de "TrnOrder ” (Tabla de origen) utilizando OPENROWSET ordenar y almacenar datos en ##Source_Trn_Table .
  2. Realice la operación INSERTAR, ACTUALIZAR y ELIMINAR en el MstStock (Tabla de destino) usando MERGE palabra clave, según las siguientes condiciones:
    • Si el valor del Product_ID la columna existe en ##Source_Trn_Table y las acciones luego actualice el stock actual en el MstStock mesa.
    • Si el valor del Product_ID la columna existe en ##Source_Trn_Table pero no existe en el MstStock luego agregue un producto a la tabla MstStock mesa.
    • Si el valor del Product_ID la columna existe en MstStock pero no existe en ##Source_Trn_Tabl e, además, el valor de la columna de last_stock_update_date es mayor a un año, luego elimine product_id de MstStock mesa.

El siguiente es el diagrama de flujo:

Demostración

Primero cree una tabla de destino llamada MstStock y MstProduct en el Product_Master base de datos, ubicada en el TTI412-VM2 servidor. Ejecute la siguiente consulta:

USE [Product_Master]
GO
CREATE TABLE [dbo].[MstProduct](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Product_ID] [varchar](15) NULL,
	[Product_Name] [varchar](500) NOT NULL,
PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
	[Product_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[MstStock](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Product_ID] [varchar](5) NOT NULL,
	[Current_Stock] [int] NULL,
	[Last_Stock_Update_Date] [datetime] NULL,
PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
	[Product_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Ahora agregue algunos datos a ambas tablas.

Ejecute la siguiente consulta para agregar datos al MstProduct tabla:

SET IDENTITY_INSERT dbo.MstProduct ON
GO
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (28, 'MED141', 'Alfimaxin')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (29, 'MED142', 'Zylasonmuc')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (30, 'MED143', 'Rythmoxabid')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (31, 'MED144', 'Omedrozol')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (32, 'MED145', 'Reducurzol')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (33, 'MED146', 'Losapuritriol')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (34, 'MED147', 'Pipepapren')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (35, 'MED148', 'Miraperahex')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (36, 'MED149', 'Durachloridevant')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (37, 'MED151', 'Renachloridenide')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (38, 'MED152', 'Ecopurimuc')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (39, 'MED153', 'Aerocarpambid')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (40, 'MED154', 'Afsitec')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (41, 'MED155', 'Aprozovant')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (42, 'MED156', 'Levopafen')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (43, 'MED157', 'Medrotraxel')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (44, 'MED158', 'Doxxaliq')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (45, 'MED159', 'Betatasine')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (46, 'MED161', 'Ciclopatex')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (47, 'MED162', 'Acadipiphane')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (48, 'MED163', 'Septomapin')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (49, 'MED164', 'Acioxenal')
INSERT dbo.MstProduct(ID, Product_ID, Product_Name) VALUES (50, 'MED165', 'Natadrolol')
GO
SET IDENTITY_INSERT dbo.MstProduct OFF
GO

Ejecute la siguiente consulta para agregar datos al MstStock tabla:

insert into MstStock (Product_ID,Current_Stock,Last_Stock_Update_Date) values ('MED145',15,'2018-10-14'),('MED146',20,'2018-10-13'),('MED147',5,'2018-09-10'),('MED150',5,'2018-08-01'),('MED158',0,'2017-10-14'),('MED159',0,'2017-10-14')

Ejecute las siguientes consultas "Seleccionar" para revisar el resultado de las tablas.

Consulta:

Use Product_Master
Go
Select * from MstProduct

Salida:

Consulta:

Use Product_Master
Go
Select * from MstStock

Salida:

En segundo lugar, cree una tabla de origen llamada TrnOrder en Inventory_Details base de datos, ubicada en el TTI412-VM1 servidor. Ejecute la siguiente consulta:

USE [Inventory_Details]
GO
CREATE TABLE [dbo].[TrnOrder](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Product_ID] [varchar](15) NOT NULL,
	[Ordered_Qty] [int] NULL,
	[Ordered_Date] [datetime] NULL,
	[Last_Ordered_Date] [datetime] NULL,
PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
	[Product_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Ejecute la siguiente consulta para agregar datos al MstStock tabla:

insert into TrnOrder (Product_ID,Ordered_Qty,Ordered_Date,Last_Ordered_Date)
values 
('MED145',10,convert(date,getdate()),'2018-10-14'),('MED146',5,convert(date,getdate()),'2018-10-13'),
('MED147',15,convert(date,getdate()),'2018-09-10'),('MED150',200,convert(date,getdate()),'2018-08-01') 
,('MED169',50,convert(date,getdate()),'2018-10-14'),('MED170',100,convert(date,getdate()),'2018-10-14')

Ejecute la siguiente consulta "Seleccionar" para revisar el resultado de la tabla.

Consulta:

Use Inventory_Details
Go
Select * from TrnOrder

Salida:

Conéctese a la instancia remota de SQL Server para completar los datos

Como mencioné, queremos actualizar los valores en la "tabla que se crea en un servidor remoto. Podemos acceder a los datos desde un servidor de base de datos remoto utilizando los siguientes métodos.

  1. Servidor vinculado a SQL Server :El servidor vinculado se utiliza para ejecutar un comando en la fuente de datos OLEDB que está vinculada a la instancia remota de SQL Server. Usando un servidor vinculado, también puede consultar el producto de base de datos diferente como Oracle. Las fuentes OLEDB se pueden configurar para acceder a Microsoft Access y Excel como un servidor vinculado.
  2. Función OPENROWSET de SQL Server :Usando la función OPENROWSET, podemos ejecutar una consulta Ad-Hoc en la fuente de datos OLEDB remota.

En este artículo, usaremos el OPENROWSET método para acceder a los datos de la tabla remota. Para consultar un servidor remoto usando la función OPENROWSET, debemos habilitar las Consultas distribuidas ad hoc parámetro de configuración.

“Consultas distribuidas ad hoc” es una opción avanzada, por lo que primero debemos habilitar la opción Mostrar opciones avanzadas parámetro de configuración. Para hacer eso, ejecute el siguiente comando en la ventana de consulta del estudio de administración de SQL Server.

exec sp_configure 'show advanced options',1
reconfigure with override
Go

Una vez que la Mostrar opción avanzada está habilitado, ejecute la siguiente consulta para habilitar Consultas distribuidas ad hoc :

sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE WITH OVERRIDE;
GO

No podemos usar la función "OPENROWSET" para realizar la operación MERGE usando datos del servidor remoto. Para hacer eso, primero debemos importar datos del servidor remoto y almacenarlos en la tabla temporal global. Después de eso, podemos usar los datos que se encuentran dentro de la tabla temporal global para actualizar la tabla de destino.

Como mencioné, primero debemos importar datos de la tabla remota. Para hacer eso, cree una tabla temporal e importe datos usando la función OPENROWSET.
La siguiente consulta creará una tabla temporal global.

use Product_Master
go
CREATE TABLE ##Source_Trn_Order
(
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Product_ID] [varchar](15) NOT NULL,
	[Ordered_Qty] [int] NULL,
	[Ordered_Date] [datetime] NULL,
	[Last_Ordered_Date] [datetime] NULL
)

Una vez que se crea la tabla temporal, carguemos datos de una tabla de origen que se encuentra en un servidor remoto. Para hacer eso, ejecute la siguiente consulta:

insert into ##Source_Trn_Order select [Product_ID],[Ordered_Qty],[Ordered_Date],[Last_Ordered_Date]  from 
OPENROWSET('SQLNCLI', 'Server=TTI609-VM1;Trusted_Connection=yes;',
'SELECT Product_ID, Ordered_Qty, Ordered_Date,Last_Ordered_Date FROM Inventory_Details.dbo.TrnOrder') AS a;

Paso 1:si existe un producto en MstStock (tabla de destino) y TrnOrder (tabla de origen), actualice la cantidad actual en MstStock

Para hacer eso, use el CUANDO COINCIDE cláusula. La cláusula une las tablas de origen y destino en las columnas comunes de ambas tablas. El ID_Producto columna es común entre MstStock y ##Source_Trn_Table, por lo tanto, utilícelo para unir ambas tablas.

Ejecuta el siguiente código:

 MERGE MstStock target_Stock
USING ##Source_Trn_Order Source_Order
ON target_Stock.Product_Id = Source_Order.Product_Id 
WHEN MATCHED THEN
  UPDATE
  SET target_Stock.Current_Stock = Source_Order.Ordered_Qty + target_Stock.Current_Stock, 
Last_Stock_Update_Date=getdate();

Se debe actualizar el valor de la columna Current_Stock de 4 productos. Ejecute la siguiente consulta para verificar la salida:

select b.Product_ID,b.Product_Name,a.Current_Stock,a.Last_Stock_Update_Date from MstStock a inner join MstProduct b on a.Product_ID=b.Product_ID and a.Current_Stock>0

El siguiente es el resultado:

Paso 2:si un producto no existe en MstStock (tabla de destino), agréguelo en MstStock (tabla de destino)

Tienda de farmacia había pedido algunos productos. Esos productos se agregaron en la tabla MstProduct pero no se agregaron a la tabla MstStock. Para agregar esos productos en el MstStock tabla, usaré la cláusula WHEN NOT MATCHED [TARGET]. La cláusula une las tablas de origen y de destino utilizando columnas comunes. Si no se encuentran filas coincidentes en la tabla de destino, inserta filas de la tabla de origen.

Para agregar productos a MstStock utilizando la COMBINACIÓN tabla, ejecute el siguiente código:

MERGE mststock target_Stock
using ##source_trn_order Source_Order
ON target_Stock.product_id = source_order.product_id
WHEN matched THEN
  UPDATE SET target_Stock.current_stock = Source_Order.ordered_qty
                                          + target_Stock.current_stock,
             last_stock_update_date = Getdate()
WHEN NOT matched BY target THEN
  INSERT (product_id,
          current_stock,
          last_stock_update_date)
  VALUES (Source_Order.product_id,
          Source_Order.ordered_qty,
          Getdate());

ID de dos productos, MED169 y MED170, debería ser añadido. Ejecute la siguiente consulta para revisar el resultado:

select b.Product_ID,b.Product_Name,a.Current_Stock,a.Last_Stock_Update_Date from MstStock a inner join MstProduct b on a.Product_ID=b.Product_ID and a.Current_Stock>0

Lo siguiente es la salida:

Paso 3:elimine el artículo de MstStock (tabla de destino), si el stock actual en MstStock (tabla de destino) es cero y el producto no está en ##Source_Trn_Order (tabla de origen)

En el inventario, hay pocos productos que deben eliminarse porque no se ordenaron durante un año. Por lo tanto, debemos eliminarlos del MstStock tabla y la tabla MstProducts. Para eliminar esos productos de MstStock tabla, podemos usar CUANDO NO COINCIDE [FUENTE] .

El CUANDO NO COINCIDE [FUENTE] La cláusula une las tablas de origen y de destino utilizando columnas comunes. Si no se encuentran filas coincidentes en la tabla de origen, elimina las filas de la tabla de destino.

Para eliminar productos de MstStock tabla, ejecute el siguiente código:

MERGE mststock target_Stock
using ##source_trn_order Source_Order
ON target_Stock.product_id = source_order.product_id
WHEN matched THEN
  UPDATE SET target_Stock.current_stock = Source_Order.ordered_qty
                                          + target_Stock.current_stock,
             last_stock_update_date = Getdate()
WHEN NOT matched BY target THEN
  INSERT (product_id,
          current_stock,
          last_stock_update_date)
  VALUES (Source_Order.product_id,
          Source_Order.ordered_qty,
          Getdate())  
WHEN NOT matched BY SOURCE THEN
  DELETE;

ID de dos productos, MED158 y MED159 debería ser añadido. Ejecute la siguiente consulta para revisar el resultado:

select b.Product_ID,b.Product_Name,a.Current_Stock,a.Last_Stock_Update_Date from MstStock a inner join MstProduct b on a.Product_ID=b.Product_ID and a.Current_Stock>0

Lo siguiente es la salida:

Resumen

En este artículo he cubierto lo siguiente:

  1. ¿Qué es la palabra clave MERGE y cómo funciona?
  2. Diferentes cláusulas utilizadas en MERGE para actualizar la tabla de origen y de destino.
  3. Cómo modificar datos usando la palabra clave MERGE cuando las bases de datos están en diferentes servidores.

Herramientas útiles:

Comparación de datos de dbForge para SQL Server:una poderosa herramienta de comparación de SQL capaz de trabajar con grandes datos.