Database
 sql >> Base de données >  >> RDS >> Database

MERGE :mise à jour des tables source et cible situées sur des serveurs distincts

Qu'est-ce que l'instruction MERGE ?

À l'aide de l'instruction MERGE, nous pouvons modifier les données d'une table cible en fonction des données d'une table source. En l'utilisant, nous pouvons exécuter INSERT, UPDATE et DELETE sur les tables cibles dans un seul bloc de requête. Il joint les deux tables à l'aide de colonnes, communes aux deux tables comme la clé primaire. En fonction de la correspondance des données de la colonne, les modifications s'appliquent aux données de la table cible. L'image suivante illustre le fonctionnement de "MERGE" :

En utilisant MERGE, nous pouvons obtenir une amélioration des performances car les trois opérations (INSERT, UPDATE et DELETE ) sont exécutés en un seul passage. Nous n'avons pas besoin d'écrire une déclaration individuelle pour mettre à jour les modifications dans la table cible.

L'instruction de fusion utilise SourceTable et Tableau de destination. Il modifie DestinationTable basé sur les données de SourceTable . Les deux tables sont comparées à l'aide de la condition définie dans l'instruction de fusion. Cette condition détermine comment SourceTable correspond à la table de destination. C'est comme les conditions de jointure qui sont utilisées pour faire correspondre les lignes.

En règle générale, la correspondance doit être effectuée en faisant correspondre des identifiants uniques tels que des clés primaires. Par exemple, la table source est NewProduct et la destination est Productmaster et la clé primaire est ProductID , la condition de fusion doit être la suivante :

NewProduct.ProductID=ProductMaster.ProdID

Voici le format de l'instruction 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

Pour modifier les données de la table cible, MERGE prend en charge les clauses T-SQL suivantes.

  1. LORSQUE CORRESPOND
  2. LORSQU'IL NE CORRESPOND PAS [PAR CIBLE]
  3. LORSQU'IL N'Y A PAS CORRESPONDANCE [PAR SOURCE]

Clause "WHEN MATCHED"

Cette clause sera utilisée lorsque nous voulons mettre à jour ou supprimer les enregistrements de la table de destination. Ici, les enregistrements sont considérés comme correspondants lorsque les données des colonnes jointes sont identiques.

Clause "WHEN NOT MATCHED [BY TARGET]"

Si l'enregistrement est présent dans la table source mais pas dans la table cible alors cette clause sera utilisée pour insérer un nouvel enregistrement dans la table cible.

Clause "WHEN NOT MATCHED [BY SOURCE]"

Cette clause sera utilisée lorsque nous voulons supprimer ou mettre à jour un enregistrement dans une table source qui ne correspond pas à une ligne dans la table cible.

Utilisez MERGE lorsque la source et la cible se trouvent sur un serveur distinct

Dans cet article, je vais montrer comment effectuer une opération d'insertion, de mise à jour et de suppression à l'aide de MERGE, lorsque les tables source et cible se trouvent sur des serveurs distincts. Par exemple, une entreprise pharmaceutique utilise un logiciel d'inventaire. Les bases de données maîtresses d'un logiciel et les bases de données transactionnelles d'un logiciel se trouvent sur des serveurs de base de données distincts. Voici une configuration :

La société a ajouté quelques produits commandés. Je souhaite effectuer quelques opérations de nettoyage lors de la mise à jour du stock de produits. Voici la liste des tâches qui doivent être effectuées.

  1. Si un produit existe en stock et que le même produit a été commandé, mettez à jour puis mettez à jour le stock.
  2. Si un produit n'existe pas dans l'inventaire et qu'un produit supplémentaire est commandé, ajoutez le produit en stock.
  3. Si le produit existe dans l'inventaire mais qu'il n'est pas commandé de plus le stock du produit n'est pas mis à jour depuis plus d'un an que supprimer le produit de l'inventaire.

Pour effectuer la tâche mentionnée ci-dessus, nous allons effectuer les étapes suivantes :

  1. Créez une table temporaire globale nommée ##Source_Trn_Tabl e. Remplir les données de "TrnOrder ” (table source) en utilisant OPENROWSET commande et stocke les données dans ##Source_Trn_Table .
  2. Effectuer les opérations INSERT, UPDATE et DELETE sur le MstStock table (table cible) à l'aide de la fonction MERGE mot-clé, selon les conditions suivantes :
    • Si la valeur de Product_ID la colonne existe dans ##Source_Trn_Table et le stock table, puis mettez à jour le stock actuel dans le MstStock tableau.
    • Si la valeur de Product_ID la colonne existe dans ##Source_Trn_Table mais n'existe pas dans le MstStock table, puis ajoutez un produit au MstStock tableau.
    • Si la valeur de Product_ID la colonne existe dans MstStock mais n'existe pas dans ##Source_Trn_Tabl e, de plus la valeur de colonne de last_stock_update_date est supérieur à un an, puis supprimez product_id à partir du MstStock tableau.

Voici l'organigramme :

Démonstration

Créez d'abord une table cible nommée MstStock et MstProduct sur le Product_Master base de données, située sur le TTI412-VM2 serveur. Exécutez la requête suivante :

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

Ajoutez maintenant des données aux deux tables.

Exécutez la requête suivante pour ajouter des données au MstProduct tableau :

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

Exécutez la requête suivante pour ajouter des données au MstStock tableau :

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')

Exécutez les requêtes "Select" suivantes pour examiner la sortie des tables.

Requête :

Use Product_Master
Go
Select * from MstProduct

Sortie :

Requête :

Use Product_Master
Go
Select * from MstStock

Sortie :

Deuxièmement, créez une table source nommée TrnOrder sur les Inventory_Details base de données, située sur le TTI412-VM1 serveur. Exécutez la requête suivante :

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

Exécutez la requête suivante pour ajouter des données au MstStock tableau :

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')

Exécutez la requête "Select" suivante pour examiner la sortie de la table.

Requête :

Use Inventory_Details
Go
Select * from TrnOrder

Sortie :

Se connecter à l'instance Remote SQL Server pour remplir les données

Comme je l'ai mentionné, nous voulons mettre à jour les valeurs dans "table qui est créée sur un serveur distant. Nous pouvons accéder aux données d'un serveur de base de données distant en utilisant les méthodes suivantes.

  1. Serveur SQL Server lié :Le serveur lié est utilisé pour exécuter une commande sur la source de données OLEDB qui est liée à l'instance distante de SQL Server. À l'aide d'un serveur lié, vous pouvez également interroger les différents produits de base de données comme Oracle. Les sources OLEDB peuvent être configurées pour accéder à Microsoft Access et Excel en tant que serveur lié.
  2. Fonction SQL Server OPENROWSET  :À l'aide de la fonction OPENROWSET, nous pouvons exécuter une requête Ad-Hoc sur la source de données OLEDB distante.

Dans cet article, nous utiliserons le OPENROWSET méthode pour accéder aux données de la table distante. Pour interroger un serveur distant à l'aide de la fonction OPENROWSET, nous devons activer les requêtes distribuées ad hoc paramètre de configuration.

"Requêtes distribuées ad hoc" est une option avancée, nous devons donc d'abord activer l'option Afficher l'option avancée paramètre de configuration. Pour ce faire, exécutez la commande suivante dans la fenêtre de requête de SQL Server Management Studio.

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

Une fois l'option Afficher l'option avancée est activé, exécutez la requête suivante pour activer les requêtes distribuées ad hoc :

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

Nous ne pouvons pas utiliser la fonction "OPENROWSET" pour effectuer une opération MERGE en utilisant les données du serveur distant. Pour ce faire, nous devons d'abord importer les données du serveur distant et les stocker dans la table temporaire globale. Après cela, nous pouvons utiliser les données contenues dans la table temporaire globale pour mettre à jour la table cible.

Comme je l'ai mentionné, nous devons d'abord importer les données de la table distante. Pour ce faire, créez une table temporaire et importez les données à l'aide de la fonction OPENROWSET.
La requête suivante créera une table temporaire globale.

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
)

Une fois la table temporaire créée, chargeons les données d'une table source située sur un serveur distant. Pour cela, exécutez la requête suivante :

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;

Étape 1 :Si un produit existe dans MstStock (table cible) et TrnOrder (table source), mettez à jour la quantité actuelle dans MstStock

Pour ce faire, utilisez le WHEN MATCHED clause. La clause joint les tables source et cible sur les colonnes communes des deux tables. Le Product_ID la colonne est commune entre MstStock et ##Source_Trn_Table, utilisez-le donc pour joindre les deux tables.

Exécutez le code suivant :

 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();

La valeur de la colonne Current_Stock de 4 produits doit être mise à jour. Exécutez la requête suivante pour vérifier le résultat :

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

Voici le résultat :

Étape 2 :Si un produit n'existe pas dans MstStock (table cible), ajoutez-le dans MstStock (table cible)

La pharmacie avait commandé quelques produits. Ces produits ont été ajoutés dans la table MstProduct mais pas dans la table MstStock. Pour ajouter ces produits dans le MstStock table, j'utiliserai la clause WHEN NOT MATCHED [TARGET]. La clause joint les tables source et cible à l'aide de colonnes communes. Si les lignes correspondantes ne sont pas trouvées dans la table cible, il insère des lignes de la table source.

Pour ajouter des produits à MstStock en utilisant la FUSIONNER table, exécutez le code suivant :

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());

Deux identifiants de produits, MED169 et MED170, devrait être ajouté. Exécutez la requête suivante pour examiner le résultat :

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

Voici la sortie :

Étape 3 :Supprimer l'article de MstStock (table cible), si le stock actuel dans MstStock (table cible) est égal à zéro et que le produit n'est pas dans ##Source_Trn_Order (table source)

En inventaire, il y a peu de produits qui doivent être supprimés car ceux-ci n'ont pas été commandés depuis un an. Par conséquent, nous devons les supprimer du MstStock table et la table MstProducts. Pour supprimer ces produits du MstStock table, nous pouvons utiliser WHEN NOT MATCHED [SOURCE] .

Le WHEN NOT MATCHED [SOURCE] La clause joint les tables source et cible à l'aide de colonnes communes. Si les lignes correspondantes ne sont pas trouvées dans la table source, il supprime les lignes de la table cible.

Pour supprimer des produits du MstStock table, exécutez le code suivant :

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;

Deux identifiants de produits, MED158 et MED159 devrait être ajouté. Exécutez la requête suivante pour examiner le résultat :

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

Voici la sortie :

Résumé

Dans cet article, j'ai couvert ce qui suit :

  1. Qu'est-ce que le mot clé MERGE et comment fonctionne-t-il ?
  2. Différentes clauses utilisées dans MERGE pour mettre à jour les tables source et cible.
  3. Comment modifier des données à l'aide du mot-clé MERGE lorsque les bases de données se trouvent sur différents serveurs.

Outils utiles :

dbForge Data Compare for SQL Server – puissant outil de comparaison SQL capable de travailler avec le Big Data.