Database
 sql >> Base de Dados >  >> RDS >> Database

MERGE:Atualizando tabelas de origem e destino localizadas em servidores separados

O que é a instrução MERGE?


Usando a instrução MERGE, podemos alterar os dados em uma tabela de destino com base nos dados de uma tabela de origem. Usando-o, podemos executar INSERT, UPDATE e DELETE nas tabelas de destino dentro de um único bloco de consulta. Ele une as duas tabelas usando colunas, comuns em ambas as tabelas, como a chave primária. Com base em como os dados da coluna correspondem, as alterações se aplicam aos dados da tabela de destino. A imagem a seguir ilustra como “MERGE” funciona:



Usando MERGE, podemos melhorar o desempenho porque todas as três operações (INSERT, UPDATE e DELETE ) são executados em uma passagem. Não precisamos escrever uma instrução individual para atualizar as alterações na tabela de destino.

A instrução de mesclagem usa SourceTable e Destinationtable. Ele modifica DestinationTable com base nos dados de SourceTable . Ambas as tabelas são comparadas usando a condição, definida na instrução Merge. Essa condição determina como SourceTable corresponde à tabela de destino. É como as condições de junção que são usadas para combinar linhas.

Normalmente, a correspondência deve ser feita combinando identificadores exclusivos, como chaves primárias. Por exemplo, a tabela de origem é NewProduct e o destino é Productmaster e a chave primária é ProductID , então a condição de mesclagem deve ser a seguinte:
NewProduct.ProductID=ProductMaster.ProdID

A seguir está o formato da instrução 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 os dados na tabela de destino, MERGE oferece suporte às seguintes cláusulas T-SQL.
  1. QUANDO COMBINADO
  2. QUANDO NÃO CORRESPONDE [POR META]
  3. QUANDO NÃO CORRESPONDENTE [PELA FONTE]

Cláusula "QUANDO CORRESPONDENTE"


Esta cláusula será usada quando quisermos atualizar ou excluir os registros da tabela de destino. Aqui, os registros são considerados como correspondentes quando os dados nas colunas unidas são os mesmos.

Cláusula "QUANDO NÃO CORRESPONDENTE [POR ALVO]"


Se o registro estiver presente na tabela de origem, mas não na tabela de destino, esta cláusula será usada para inserir um novo registro na tabela de destino.

Cláusula "QUANDO NÃO CORRESPONDENTE [PELA FONTE]"


Esta cláusula será usada quando quisermos excluir ou atualizar um registro em uma tabela de origem que não corresponda a uma linha na tabela de destino.

Use MERGE quando a origem e o destino estiverem em um servidor separado


Neste artigo, vou demonstrar como realizar a operação de inserção, atualização e exclusão usando MERGE, quando as tabelas de origem e destino estão em servidores separados. Por exemplo, uma empresa farmacêutica usa software de inventário. Os bancos de dados mestre de um software e os bancos de dados transacionais de software estão em servidores de banco de dados separados. Segue uma configuração:



A empresa adicionou alguns produtos encomendados. Desejo realizar alguns processos de limpeza ao atualizar o estoque de produtos. Segue a lista de tarefas que devem ser executadas.
  1. Se houver um produto no estoque e o mesmo produto foi pedido, atualize e atualize o estoque.
  2. Se um produto não existir no inventário e adicionar produto for pedido, adicione o produto em estoque.
  3. Se o produto existir no estoque, mas não for pedido, o estoque do produto não for atualizado por mais de um ano, exclua o produto do estoque.

Para realizar a tarefa acima mencionada, realizaremos as seguintes etapas:
  1. Crie uma tabela temporária global chamada ##Source_Trn_Tabl e. Preencher dados de “TrnOrder ” (Tabela de origem) usando o OPENROWSET comando e armazene dados em ##Source_Trn_Table .
  2. Execute a operação INSERT, UPDATE e DELETE no MstStock tabela (Tabela de destino) usando o MERGE palavra-chave, com base nas seguintes condições:
    • Se o valor do Product_ID coluna existe em ##Source_Trn_Table e o estoque tabela e atualize o estoque atual no MstStock tabela.
    • Se o valor do Product_ID a coluna existe em ##Source_Trn_Table mas não existe no MstStock tabela e adicione um produto ao MstStock tabela.
    • Se o valor do Product_ID coluna existe em MstStock mas não existe em ##Source_Trn_Tabl e, além disso, o valor da coluna de last_stock_update_date for maior que um ano, exclua product_id do MstStock tabela.

Segue o fluxograma:


Demonstração


Primeiro, crie uma tabela de destino chamada MstStock e MstProduto no Product_Master banco de dados, localizado no TTI412-VM2 servidor. Execute a seguinte 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

Agora adicione alguns dados a ambas as tabelas.

Execute a seguinte consulta para adicionar dados ao MstProduct tabela:
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

Execute a seguinte consulta para adicionar dados ao MstStock tabela:
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')

Execute as seguintes consultas “Selecionar” para revisar a saída das tabelas.

Consulta:
Use Product_Master
Go
Select * from MstProduct

Saída:



Consulta:
Use Product_Master
Go
Select * from MstStock

Saída:



Em segundo lugar, crie uma tabela de origem chamada TrnOrder em Inventário_Detalhes banco de dados, localizado no TTI412-VM1 servidor. Execute a seguinte 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

Execute a seguinte consulta para adicionar dados ao MstStock tabela:
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')

Execute a seguinte consulta “Select” para revisar a saída da tabela.

Consulta:
Use Inventory_Details
Go
Select * from TrnOrder

Saída:


Conecte-se à instância remota do SQL Server para preencher os dados


Como mencionei, queremos atualizar os valores na “tabela que é criada em um servidor remoto. Podemos acessar dados de um servidor de banco de dados remoto usando os seguintes métodos.
  1. Servidor vinculado ao SQL Server :O servidor vinculado é usado para executar um comando na fonte de dados OLEDB que está vinculada à instância remota do SQL Server. Usando um servidor vinculado, você também pode consultar o produto de banco de dados diferente, como o Oracle. As fontes OLEDB podem ser configuradas para acessar o Microsoft Access e o Excel como um servidor vinculado.
  2. Função OPENROWSET do SQL Server :Usando a função OPENROWSET, podemos executar uma consulta Ad-Hoc na fonte de dados OLEDB remota.

Neste artigo, usaremos o OPENROWSET método para acessar os dados da tabela remota. Para consultar um servidor remoto usando a função OPENROWSET, devemos habilitar as Consultas distribuídas ad hoc parâmetro de configuração.

“Consultas distribuídas ad hoc” é uma opção avançada, portanto, primeiro devemos habilitar a opção Mostrar avançada parâmetro de configuração. Para fazer isso, execute o seguinte comando na janela Consulta do SQL Server Management Studio.
exec sp_configure 'show advanced options',1
reconfigure with override
Go

Quando a Mostrar opção avançada estiver habilitado, execute a seguinte consulta para habilitar Consultas distribuídas ad hoc :
sp_configure 'Ad Hoc Distributed Queries', 1;
RECONFIGURE WITH OVERRIDE;
GO

Não podemos usar a função “OPENROWSET” para executar a operação MERGE usando dados do servidor remoto. Para fazer isso primeiro devemos importar os dados do servidor remoto e armazená-los na tabela temporária global. Depois disso, podemos usar os dados contidos na tabela temporária global para atualizar a tabela de destino.

Como mencionei, primeiro devemos importar os dados da tabela remota. Para fazer isso, crie uma tabela temporária e importe os dados usando a função OPENROWSET.
A consulta a seguir criará uma tabela temporária 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
)

Depois que a tabela temporária for criada, vamos carregar os dados de uma tabela de origem localizada em um servidor remoto. Para isso, execute a seguinte 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;

Etapa 1:Se um produto existir em MstStock (Tabela de destino) e TrnOrder (Tabela de origem), atualize a quantidade atual em MstStock


Para fazer isso, use o QUANDO CORRESPONDENTE cláusula. A cláusula une as tabelas Origem e Destino nas colunas comuns de ambas as tabelas. O Product_ID coluna é comum entre MstStock e ##Source_Trn_Table, portanto, use-o para unir as duas tabelas.

Execute o seguinte 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();

Valor da coluna Current_Stock de 4 produtos deve ser atualizado. Execute a seguinte consulta para verificar a saída:
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 a saída:


Etapa 2:se um produto não existir em MstStock (Tabela de destino), adicione-o em MstStock (Tabela de destino)


A farmácia tinha encomendado alguns produtos. Esses produtos foram adicionados na tabela MstProduct, mas não foram adicionados à tabela MstStock. Para adicionar esses produtos no MstStock tabela, usarei a cláusula WHEN NOT MATCHED [TARGET]. A cláusula une as tabelas de origem e destino usando colunas comuns. Se as linhas correspondentes não forem encontradas na tabela de destino, ele insere as linhas da tabela de origem.

Para adicionar produtos ao MstStock usando o MERGE tabela, execute o seguinte 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());

Dois IDs de produtos, MED169 e MED170, deve ser adicionado. Execute a seguinte consulta para revisar a saída:
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 a saída:


Etapa 3:Excluir item de MstStock (Tabela de destino), se o estoque atual em MstStock (Tabela de destino) for zero e o produto não estiver em ##Source_Trn_Order (tabela de origem)


No estoque, há poucos produtos que precisam ser excluídos porque não são pedidos há um ano. Portanto, devemos excluí-los do MstStock tabela e a tabela MstProducts. Para excluir esses produtos do MstStock tabela, podemos usar WHEN NOT MATCHED [SOURCE] .

O QUANDO NÃO CORRESPONDE [FONTE] cláusula une tabelas de origem e destino usando colunas comuns. Se as linhas correspondentes não forem encontradas na tabela de origem, ele excluirá as linhas da tabela de destino.

Para remover produtos do MstStock tabela, execute o seguinte 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;

Dois IDs de produtos, MED158 e MED159 deve ser adicionado. Execute a seguinte consulta para revisar a saída:
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 a saída:


Resumo


Neste artigo eu abordei o seguinte:
  1. O que é a palavra-chave MERGE e como ela funciona?
  2. Diferentes cláusulas usadas em MERGE para atualizar a tabela de origem e destino.
  3. Como modificar dados usando a palavra-chave MERGE quando os bancos de dados estão em servidores diferentes.


Ferramentas úteis:


dbForge Data Compare for SQL Server – poderosa ferramenta de comparação SQL capaz de trabalhar com big data.