sql >> Database teknologi >  >> RDS >> Sqlserver

Use Cases for SQL Server MERGE Statement:Synkronisering af online- og historietabeller

INTRODUKTION

SQL Server MERGE-sætningen er et utroligt nyttigt værktøj til at udføre DML-operationer baseret på sammenligning af to tabeller eller to datasæt. Brug af denne erklæring er faktisk som at udføre flere operationer i en enkelt sætning.

Denne artikel vil udforske tre use cases, der grænser op til at sikre, at data mellem en onlinetabel og en historietabel er synkroniseret.

Lad os beskrive scenariet i et par skitserede udsagn, som ville være velkendte for mange DBA'er eller udviklere:

  1. Kildetabellen kaldet Tran fanger transaktioner, der sker i realtid på en løbende basis.
  2. Den aftalte opbevaringsperiode for tabel Tran er en måned. Tran skal renses i slutningen af ​​hver måned.
  3. Dagligt skal Trans data sendes til TranHistory under "Slut på dagen".
  4. TranHistory tabel er en historisk tabel, der samler transaktionsdata over et år.
  5. Alle indsættelser og opdateringer på Tran tabellen skal afspejle i TranHistory tabel i slutningen af ​​hver dag.

FORBEREDELSE AF SCENARIOET

Scenariet beskrevet ovenfor indebærer, at poster i Tran-tabellen også findes i tabellen TranHistory, indtil de renses månedligt. Hver dag vil der være et par nye poster i Tran-tabellen, men IKKE i TranHistory-tabellen. Vi skal finde en måde at indsætte disse nye rækker på.

Lad os først forberede de pågældende tabeller (se liste 1 og 2).

-- Listing 1: Create Tran Table
USE AU
GO
CREATE TABLE [Tran] (
  responseId int NOT NULL ,
  senderId varchar(15) ,
  msisdn varchar(15) ,
  [message] varbinary ,
  status smallint ,
  application varchar ,
  receivedTime timestamp NULL ,
  processedTime datetime2 NULL ,
  flag smallint ,
  requestDelivery smallint ,
  delivered smallint ,
  account varchar(20) ,
  srcTon smallint ,
  srcNpi smallint ,
  destTon smallint ,
  destNpi smallint ,
  errorCode smallint ,
  messageId varchar ,
  sequenceNo int ,
  retries smallint ,
  messagePriority int ,
  userId varchar(20) ,
  bulkId varchar(20) 
)
-- Listing 2: Create TranHistory Table
USE AU
GO
CREATE TABLE [TranHistory] (
  responseId int NOT NULL ,
  senderId varchar(15) ,
  msisdn varchar(15) ,
  [message] varchar(160) ,
  status smallint ,
  application varchar ,
  receivedTime datetime2 NULL ,
  processedTime datetime2 NULL ,
  flag smallint ,
  requestDelivery smallint ,
  delivered smallint ,
  account varchar(20) ,
  srcTon smallint ,
  srcNpi smallint ,
  destTon smallint ,
  destNpi smallint ,
  errorCode smallint ,
  messageId varchar ,
  sequenceNo int ,
  retries smallint ,
  messagePriority int ,
  userId varchar(20) ,
  bulkId varchar(20) ,
  archivedTime datetime2 NOT NULL ,
)

NÅR DET IKKE MATCHES, SÅ INDSÆT

Ved at bruge koden i liste 3 indsætter vi et par rækker i Tran-tabellen for at komme i gang. Derefter fortsætter vi med at bruge en MERGE-sætning til at flytte dataene til TranHistory-tabellen.

-- Listing 3: Insert Initial Set of Rows in Tran Table
USE [AU]
GO

INSERT INTO [dbo].[Tran]
     VALUES
           (8000,'0233456789','Wishing you a Happy New Year',1,'K','20201110 15:00:00','20201110 15:10:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(7777,'0233456789','The blessing of the Lord be with you',1,'K','20201110 08:00:00','20201110 08:10:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(7005,'0234876789','Happy Birthday to you',1,'K','20201110 09:00:00','20201110 09:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(9002,'0233456789','Merry Christmas',1,'K','20201110 07:00:00','20201110 07:15:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6789,'0233467889','Buy our brand new cars for less than $8000',1,'K','20201110 14:00:00','20201110 14:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(7685,'0244556789','Happy New Month. God bless and increase you',1,'K','20201110 17:00:00','20201110 17:08:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(4983,'0229856789','Help is coming your way today!',1,'K','20201110 19:00:00','20201110 19:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6879,'0239986789','Call us for your next relocation project',1,'K','20201110 19:15:00','20201110 19:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(4567,'0233456789','Hard Work Always Pays',1,'K','20201110 22:05:00','20201110 22:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(8890,'0244656733','Don''t wait to buy land, buy land and wait',1,'K','20201110 15:05:00','20201110 15:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6789,'0233466734','We are relocating. Call us on 077788997',1,'K','20201110 18:02:00','20201110 18:17:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(9899,'0233456556','Watch out for our latest movie',1,'K','20201110 06:00:00','20201110 06:02:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6789,'0233456338','We are here to make you happy',1,'K','20201110 12:16:00','20201110 12:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
GO

Vi kunne have gjort dette på en meget enklere måde, men vi ønsker at vise MERGE-sætningssyntaksen (se liste 4):

-- Listing 4: Merge Records in Tran Table to TranHistory Table
MERGE INTO [TranHistory] a USING [Tran] b
ON a.responseId=b.responseID
WHEN NOT MATCHED BY TARGET THEN INSERT
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],[archivedTime])
 VALUES 
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],getdate());
GO

MERGE-erklæringen siger:

  1. Tag indholdet af [Tran]-tabellen og sammenlign dem med [TranHistory]-tabellen baseret på responseId kolonne.
  2. Indsæt de rækker, som du finder i kildetabellen, men som ikke finder i måltabellen (TranHistory).

Som det er ligger Tran og TranHistory på pr. Men antag, at den følgende dag introduceres nye rækker i Trans-tabellen. Vi skal også skubbe dem til TransHistory-tabellen, mens vi beholder poster i Tran-tabellen, indtil måneden er omme.

Vi bruger igen scriptet i liste 4. Denne gang tilføjer vi en OUTPUT-klausul for at fortælle, hvad der blev introduceret (se liste 5):

-- Listing 5: Merge Records in Tran Table to TranHistory Table (Add OUTPUT Clause)
USE AU
GO

MERGE INTO [TranHistory] a USING [Tran] b
ON a.responseId=b.responseID
WHEN NOT MATCHED BY TARGET THEN INSERT
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],[archivedTime])
 VALUES 
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],getdate())
OUTPUT deleted.*, $action, inserted.*;
GO

Vi kan gentage denne proces efter at have introduceret yderligere rækker til Tran-tabellen (liste 6 og 7), og vi får lignende adfærd:

-- Listing 6: Insert Six New Rows in Tran Table
USE [AU]
GO

INSERT INTO [dbo].[Tran]
     VALUES
			(6879,'0239986789','Call us for your next relocation project',1,'K','20201110 19:15:00','20201110 19:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(4567,'0233456789','Hard Work Always Pays',1,'K','20201110 22:05:00','20201110 22:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(8890,'0244656733','Don''t wait to buy land, buy land and wait',1,'K','20201110 15:05:00','20201110 15:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6789,'0233466734','We are relocating. Call us on 077788997',1,'K','20201110 18:02:00','20201110 18:17:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(9899,'0233456556','Watch out for our latest movie',1,'K','20201110 06:00:00','20201110 06:02:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(6789,'0233456338','We are here to make you happy',1,'K','20201110 12:16:00','20201110 12:20:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
GO
-- Listing 7: Insert Additional Three Rows in Tran Table
USE [AU]
GO

INSERT INTO [dbo].[Tran]
     VALUES
	(7789,'0233456433','Are you ready for your next level?',1,'K','20201110 14:35:00','20201110 14:40:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(8000,'0233457759','Hutchies Honey, another level of taste',1,'K','20201110 08:00:00','20201110 08:08:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(7777,'0233458909','Make sure you vote tomorrow',1,'K','20201110 09:45:00','20201110 09:50:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
			,(9890,'0233459994','Wishing you a Merry Christmas',1,'K','20201110 10:00:00','20201110 10:05:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
GO

NÅR SAMMENLIGNENDE OPDATERES SÅ

Et andet tilfælde er en opdatering til live-tabellen (Tran), når vi ønsker at synkronisere sådanne opdateringer til TranHistory-tabellen. Vi opretter dette scenarie ved at opdatere rækker i Tran-tabellen ved hjælp af scriptet i liste 8.

-- Listing 8: Update and Insert Rows in Tran Table
USE AU
GO

UPDATE [dbo].[Tran] SET account='JUNIPER' 
WHERE account='KAIROS';
GO

INSERT INTO [dbo].[Tran]
     VALUES
	(5578,'0233566933','Newest on the Block!',1,'K','20201110 14:35:00','20201110 14:40:00',1,1,1,'KAIROS',1,2,3,4,1,1,9789,2,1,'ROUTEMOBILE','9988776')
GO

Figur 6 viser, at rækker er opdateret i destinationstabellen. Vi får denne detalje ved hjælp af OUTPUT-sætningen.

Vi skal bruge klausulen fremhævet i liste 9. MERGE-sætningen identificerede rækker, der matcher JOIN-betingelsen og opdaterer dataene i den angivne kolonne (konto ). Vi kan opdatere flere rækker med denne tilgang.

-- Listing 9: Sync Data in TranHistory by Updating Rows
USE AU
GO

MERGE INTO [TranHistory] a USING [Tran] b
ON a.responseId=b.responseID
WHEN MATCHED THEN UPDATE
SET a.account=b.account
WHEN NOT MATCHED BY TARGET THEN INSERT
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],[archivedTime])
 VALUES 
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],getdate())
OUTPUT deleted.*, $action, inserted.*;
GO

NÅR DET IKKE ER SLETT EFTER KILDE, SLET SÅ

Endnu et scenarie involverer rækker, der slettes fra kildetabellen (liste 10). Når det sker, skal vi identificere de rækker, der ikke længere findes i kildetabellen, og fjerne dem fra destinationstabellen.

Vi opnår dette ved at bruge klausulen fremhævet i liste 10. Igen viser figur 7 og 8 rækkerne, der er påvirket af denne MERGE-sætning.

-- Listing 10: Update and Insert Rows in Tran Table
USE AU
GO

DELETE FROM [dbo].[Tran] 
WHERE account='JUNIPER';
GO
-- Listing 11: Syncing Tables After Deleting from Tran Table
USE AU
GO

MERGE INTO [TranHistory] a USING [Tran] b
ON a.responseId=b.responseID
WHEN NOT MATCHED BY SOURCE THEN DELETE
WHEN MATCHED THEN UPDATE
SET a.account=b.account
WHEN NOT MATCHED BY TARGET THEN INSERT
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],[archivedTime])
 VALUES 
([responseId],[senderId],[msisdn],[message],[status],[application],[receivedTime],[processedTime],[flag],[requestDelivery],[delivered],[account],[srcTon],[srcNpi],[destTon],[destNpi],[errorCode],[messageId],[sequenceNo],[retries],[messagePriority],[userId],[bulkId],getdate())
OUTPUT deleted.*, $action, inserted.*;
GO

Figur 7 viser rækkerne, der blev slettet, og figur 8 viser dem, der blev opdateret. Det er kraften af MERGE-erklæringen. Vi kan udføre sletnings-, indsættelses- og opdateringsoperationer i én erklæring.

KONKLUSION

Denne artikel gennemgik brugen af ​​MERGE-sætningen til at synkronisere data mellem en onlinetabel og en historiktabel, mens den ønskede opbevaring påkrævet i begge tabeller bibeholdes.

Der er mange andre use cases for SQL Server MERGE-sætninger, der ikke er dækket af denne artikel, men de er udforsket i Microsoft-dokumentation. Kildedata angivet i USING-sætningen er ikke begrænset til tabeller. Resultatsæt fra eksplicitte SELECT-sætninger kan være kildedata. Almindelige tabeludtryk kan også være kildedata.

REFERENCER

FLET i Transact-SQL


  1. Gør SQL Server-ydeevne let

  2. Hvad er praktiske forskelle mellem 'REPLACE' og 'INSERT ... ON DUPLICATE KEY UPDATE' i MySQL?

  3. hvordan man henter billede fra drawable i henhold til deres navne i SQLite-databasen og derefter viser det i listevisning

  4. Hvordan kalder man Oracle-funktion eller lagret procedure ved hjælp af fjederpersistensramme?