Cos'è l'istruzione MERGE?
Utilizzando l'istruzione MERGE, possiamo modificare i dati in una tabella di destinazione in base ai dati in una tabella di origine. Usandolo, possiamo eseguire INSERT, UPDATE e DELETE sulle tabelle di destinazione all'interno di un singolo blocco di query. Unisce entrambe le tabelle utilizzando colonne, comuni in entrambe le tabelle come la chiave primaria. In base alla corrispondenza dei dati della colonna, le modifiche si applicano ai dati della tabella di destinazione. L'immagine seguente illustra come funziona "MERGE":
Utilizzando MERGE, possiamo ottenere un miglioramento delle prestazioni perché tutte e tre le operazioni (INSERT, UPDATE ed DELETE ) vengono eseguiti in un passaggio. Non è necessario scrivere una singola istruzione per aggiornare le modifiche nella tabella di destinazione.
L'istruzione merge utilizza SourceTable e Tabella di destinazione. Modifica DestinationTable sulla base dei dati di SourceTable . Entrambe le tabelle vengono confrontate utilizzando la condizione definita nella dichiarazione di fusione. Questa condizione determina il modo in cui SourceTable corrisponde alla tabella di destinazione. È come le condizioni di unione utilizzate per abbinare le righe.
In genere, la corrispondenza dovrebbe essere eseguita abbinando identificatori univoci come le chiavi primarie. Ad esempio, la tabella di origine è NewProduct e la destinazione è Productmaster e la chiave primaria è ProductID , quindi la condizione di unione dovrebbe essere la seguente:
NewProduct.ProductID=ProductMaster.ProdID
Di seguito è riportato il formato dell'istruzione 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
Per modificare i dati sulla tabella di destinazione, MERGE supporta le seguenti clausole T-SQL.
- QUANDO ABBINATO
- QUANDO NON ABBINATO [PER TARGET]
- QUANDO NON ABBINATO [PER FONTE]
Clausola "WHEN MATCHED"
Questa clausola verrà utilizzata quando vogliamo aggiornare o eliminare i record sulla tabella di destinazione. Qui i record sono considerati corrispondenti quando i dati all'interno delle colonne unite sono gli stessi.
Clausola "QUANDO NON ABBINATO [PER TARGET]"
Se il record è presente nella tabella di origine ma non nella tabella di destinazione, questa clausola verrà utilizzata per inserire un nuovo record nella tabella di destinazione.
Clausola "QUANDO NON ABBINATO [PER FONTE]"
Questa clausola verrà utilizzata quando desideriamo eliminare o aggiornare un record in una tabella di origine che non corrisponde a una riga nella tabella di destinazione.
Usa MERGE quando sorgente e destinazione si trovano su un server separato
In questo articolo, dimostrerò come eseguire operazioni di inserimento, aggiornamento ed eliminazione utilizzando MERGE, quando le tabelle di origine e di destinazione si trovano in server separati. Ad esempio, un'azienda farmaceutica utilizza un software di inventario. I database master di un software e i database transazionali del software si trovano su server di database separati. Quella che segue è una configurazione:
L'azienda ha aggiunto alcuni prodotti ordinati. Voglio eseguire alcuni processi di pulizia durante l'aggiornamento dello stock di prodotti. Di seguito è riportato l'elenco delle attività che devono essere eseguite.
- Se un prodotto è presente nell'inventario ed è stato ordinato lo stesso prodotto, aggiorna e poi aggiorna lo stock.
- Se un prodotto non esiste nell'inventario e aggiungi un prodotto viene ordinato, aggiungi il prodotto in magazzino.
- Se il prodotto è presente nell'inventario ma non è ordinato, inoltre, lo stock del prodotto non viene aggiornato per più di un anno prima di eliminare il prodotto dall'inventario.
Per eseguire l'attività sopra menzionata, eseguiremo i seguenti passaggi:
- Crea una tabella temporanea globale denominata ##Source_Trn_Tabl e. Compila i dati da "TrnOrder ” (Tabella di origine) utilizzando OPENROWSET comanda e archivia i dati in ##Source_Trn_Table .
- Esegui l'operazione INSERT, UPDATE ed DELETE su MstStock tabella (tabella di destinazione) utilizzando MERGE parola chiave, in base alle seguenti condizioni:
- Se il valore di ID_prodotto la colonna esiste in ##Source_Trn_Table e le azioni tabella, quindi aggiorna lo stock corrente in MstStock tabella.
- Se il valore di ID_prodotto la colonna esiste in ##Source_Trn_Table ma non esiste nel MstStock tabella, quindi aggiungi un prodotto a MstStock tabella.
- Se il valore di ID_prodotto esiste una colonna in MstStock ma non esiste in ##Source_Trn_Tabl e, inoltre, il valore della colonna di last_stock_update_date è maggiore di un anno, quindi elimina id_prodotto dal MstStock tabella.
Di seguito il diagramma di flusso:
Dimostrazione
Innanzitutto crea una tabella di destinazione denominata MstStock e MstProduct nel Product_Master database, che si trova su TTI412-VM2 server. Esegui la seguente query:
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
Ora aggiungi alcuni dati a entrambe le tabelle.
Esegui la query seguente per aggiungere dati a MstProduct tabella:
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
Eseguire la query seguente per aggiungere dati a MstStock tabella:
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')
Esegui le seguenti query "Seleziona" per rivedere l'output delle tabelle.
Query:
Use Product_Master Go Select * from MstProduct
Risultato:
Query:
Use Product_Master Go Select * from MstStock
Risultato:
In secondo luogo, crea una tabella di origine denominata TrnOrder nei Dettagli_inventario database, che si trova su TTI412-VM1 server. Esegui la seguente query:
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
Eseguire la query seguente per aggiungere dati a MstStock tabella:
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')
Esegui la seguente query "Seleziona" per rivedere l'output della tabella.
Query:
Use Inventory_Details Go Select * from TrnOrder
Risultato:
Connetti all'istanza remota di SQL Server per popolare i dati
Come accennato, vogliamo aggiornare i valori nella "tabella creata su un server remoto. Possiamo accedere ai dati da un server di database remoto utilizzando i seguenti metodi.
- Server collegato a SQL Server :il server collegato viene utilizzato per eseguire un comando sull'origine dati OLEDB collegata all'istanza remota di SQL Server. Utilizzando un server collegato, puoi anche eseguire query su diversi prodotti di database come Oracle. Le origini OLEDB possono essere configurate per accedere a Microsoft Access ed Excel come server collegato.
- Funzione OPENROWSET di SQL Server :Utilizzando la funzione OPENROWSET, possiamo eseguire una query Ad-Hoc sull'origine dati OLEDB remota.
In questo articolo utilizzeremo OPENROWSET metodo per accedere ai dati della tabella remota. Per interrogare un server remoto utilizzando la funzione OPENROWSET, dobbiamo abilitare le Query distribuite ad hoc parametro di configurazione.
"Query distribuite ad hoc" è un'opzione avanzata, quindi in primo luogo dobbiamo abilitare l'opzione Mostra opzioni avanzate parametro di configurazione. Per farlo, esegui il comando seguente nella finestra Query di SQL Server Management Studio.
exec sp_configure 'show advanced options',1 reconfigure with override Go
Dopo aver selezionato Mostra opzione avanzata parametro è abilitato, eseguire la query seguente per abilitare le Query distribuite ad hoc :
sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE WITH OVERRIDE; GO
Non è possibile utilizzare la funzione "OPENROWSET" per eseguire l'operazione MERGE utilizzando i dati del server remoto. Per farlo prima dobbiamo importare i dati dal server remoto e archiviarli nella tabella temporanea globale. Successivamente, possiamo utilizzare i dati mentiti all'interno della tabella temporanea globale per aggiornare la tabella di destinazione.
Come ho già detto, in primo luogo dobbiamo importare i dati dalla tabella remota. A tale scopo, crea una tabella temporanea e importa i dati utilizzando la funzione OPENROWSET.
La query seguente creerà una tabella temporanea 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 )
Una volta creata la tabella temporanea, carichiamo i dati da una tabella di origine che si trova su un server remoto. Per farlo, esegui la seguente query:
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;
Passaggio 1:se un prodotto esiste in MstStock (tabella di destinazione) e TrnOrder (tabella di origine), aggiorna la quantità corrente in MstStock
Per farlo, usa il QUANDO ABBINATO clausola. La clausola unisce le tabelle Source e Target sulle colonne comuni di entrambe le tabelle. L'ID_prodotto colonna è comune tra MstStock e ##Source_Trn_Table, quindi usalo per unire entrambe le tabelle.
Esegui il seguente codice:
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();
Il valore della colonna Current_Stock di 4 prodotti deve essere aggiornato. Eseguire la query seguente per verificare l'output:
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
Di seguito è riportato l'output:
Fase 2:se un prodotto non esiste in MstStock (tabella target), aggiungilo in MstStock (tabella target)
La farmacia aveva ordinato alcuni prodotti. Questi prodotti sono stati aggiunti nella tabella MstProduct ma non nella tabella MstStock. Per aggiungere quei prodotti nel MstStock tabella, userò la clausola WHEN NOT MATCHED [TARGET]. La clausola unisce le tabelle di origine e di destinazione utilizzando colonne comuni. Se le righe corrispondenti non vengono trovate nella tabella di destinazione, inserisce le righe dalla tabella di origine.
Per aggiungere prodotti a MstStock utilizzando UNISCI tabella, eseguire il codice seguente:
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());
Due ID prodotti, MED169 e MED170, dovrebbe essere aggiunto. Esegui la query seguente per rivedere l'output:
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
Segue l'output:
Fase 3:elimina l'articolo da MstStock (tabella di destinazione), se lo stock corrente in MstStock (tabella di destinazione) è zero e il prodotto non è in ##Source_Trn_Order (tabella di origine)
Nell'inventario, ci sono pochi prodotti che devono essere eliminati perché non sono stati ordinati per un anno. Quindi, dobbiamo eliminarli da MstStock tabella e la tabella MstProducts. Per eliminare quei prodotti da MstStock tabella, possiamo usare QUANDO NON ABBINATO [FONTE] .
Il QUANDO NON ABBINATO [FONTE] la clausola unisce le tabelle di origine e di destinazione utilizzando colonne comuni. Se le righe corrispondenti non vengono trovate nella tabella di origine, vengono eliminate le righe dalla tabella di destinazione.
Per rimuovere prodotti da MstStock tabella, eseguire il codice seguente:
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;
Due ID prodotti, MED158 e MED159 dovrebbe essere aggiunto. Esegui la query seguente per rivedere l'output:
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
Segue l'output:
Riepilogo
In questo articolo ho trattato quanto segue:
- Cos'è la parola chiave MERGE e come funziona?
- Diverse clausole utilizzate in MERGE per aggiornare la tabella di origine e di destinazione.
- Come modificare i dati utilizzando la parola chiave MERGE quando i database si trovano su server diversi.
Strumenti utili:
dbForge Data Compare per SQL Server:potente strumento di confronto SQL in grado di lavorare con i big data.