Sök…


Introduktion

Från och med SQL Server 2008 är det möjligt att utföra infoga, uppdatera eller radera operationer i ett enda uttalande med MERGE-uttalandet.

Med MERGE-uttalandet kan du gå med i en datakälla med en måltabell eller vy och sedan utföra flera åtgärder mot målet baserat på resultaten från det sammanfogande.

Syntax

  • Enligt MSDN - https://msdn.microsoft.com/en-us/library/bb510625.aspx [MED <common_table_expression> [, ... n]] MERGE [TOP (expression) [PERCENT]] [INTO] < target_table> [MED (<merge_hint>)] [[AS] table_alias] ANVÄNDER <table_source> ON <merge_search_condition> [WHEN MATCHED [AND <clause_search_condition>] THEN <merge_matched>] [... n] [WHEN NOT MATCHED [BY MÅL] [OCH <clause_search_condition>] DÄN <merge_not_matched]] [NÄR INTE KOMMERDE AV KÄLLA [OCH <clause_search_condition>] THEN <merge_matched>] [... n] [<output_clause>] [OPTION (<query_hint> [,. ..n])]; <target_table> :: = {[databasnamn. schema_name. | schema_name. ] target_table} <merge_hint> :: = {{[<table_hint_limited> [, ... n]] [[,] INDEX (index_val [, ... n])]}} <table_source> :: = {table_or_view_name [ [AS] table_alias] [<tabellerample_clause>] [MED (table_hint [[,] ... n])] | rowset_function [[AS] table_alias] [(bulk_column_alias [, ... n])] | user_defined_function [[AS] table_alias] | OPENXML <openxml_clause> | deriv_table [AS] table_alias [(column_alias [, ... n])] | <joined_table> | <pivoted_table> | <unpivoted_table>} <merge_search_condition> :: = <search_condition> <merge_matched> :: = {UPDATE SET <set_clause> | DELETE} <set_clause> :: = SET {column_name = {expression | FUNKTION | NULL} | {udt_column_name. {{property_name = expression | field_name = expression} | metodnamn (argument [, ... n])}} | column_name {.WRITE (expression, @Offset, @Length)} | @variable = uttryck | @variable = kolumn = uttryck | column_name {+ = | - = | * = | / = | % = | & = | ^ = | | =} uttryck | @variable {+ = | - = | * = | / = | % = | & = | ^ = | | =} uttryck | @variable = kolumn {+ = | - = | * = | / = | % = | & = | ^ = | | =} uttryck} [, ... n] <merge_not_match> :: = {INSERT [(column_list)] {VALUES (Values_list) | DEFAULT VALUES}} <clause_search_condition> :: = <search_condition> :: = {[NOT] | (<sök_kondition>)} [{OCH | ELLER} [INTE] {| (<sök_kondition>)}] [, ... n] :: = {uttryck {= | <> | ! = |

    | > = | ! > | <| <= | ! <} uttryck | string_expression [NOT] LIKE string_expression [ESCAPE 'escape_character'] | uttryck [INTE] MELLAN uttryck OCH uttryck | uttrycket är [INTE] NULL | INNEHÅLLER ({kolumn | *}, '<innehåller_sök_situation>') | FREETEXT ({kolumn | *}, 'freetext_string') | uttryck [INTE] IN (underskrift | uttryck [, ... n]) | uttryck {= | <> | ! = | | > = | ! > | <| <= | ! <} {ALLA | NOG | ANY} (undersökning) | EXISTER (subfråga)} <output_clause> :: = {[OUTPUT <dml_select_list> INTO {@table_variable | output_table} [(column_list)]] [OUTPUT <dml_select_list>]} <dml_select_list> :: = {<column_name> | scalar_expression} [[AS] column_alias_identifier] [, ... n] <column_name> :: = {DELETED | INSTÄLLT | from_table_name}. {* | column_name} | $ åtgärd

Anmärkningar

Utför infoga, uppdatera eller radera operationer på en måltabell baserat på resultaten från en koppling med en källtabell. Till exempel kan du synkronisera två tabeller genom att infoga, uppdatera eller radera rader i en tabell baserat på skillnader i den andra tabellen.

FÖLJ till att infoga / uppdatera / radera

MERGE INTO targetTable

USING sourceTable 
ON (targetTable.PKID = sourceTable.PKID)

WHEN MATCHED AND (targetTable.PKID > 100) THEN
    DELETE

WHEN MATCHED AND (targetTable.PKID <= 100) THEN 
    UPDATE SET 
        targetTable.ColumnA = sourceTable.ColumnA, 
        targetTable.ColumnB = sourceTable.ColumnB

WHEN NOT MATCHED THEN
    INSERT (ColumnA, ColumnB) VALUES (sourceTable.ColumnA, sourceTable.ColumnB);

WHEN NOT MATCHED BY SOURCE THEN
    DELETE
; --< Required

Beskrivning:

  • MERGE INTO targetTable - tabell som ska modifieras
  • USING sourceTable - USING sourceTable (kan vara en tabell eller visa eller tabellvärderad funktion)
  • ON ... - targetTable tillstånd mellan targetTable och sourceTable .
  • WHEN MATCHED - åtgärder som ska WHEN MATCHED när en matchning hittas
    • AND (targetTable.PKID > 100) - ytterligare villkor som måste vara uppfyllda för att åtgärden ska kunna vidtas
  • THEN DELETE - ta bort matchad post från targetTable
  • THEN UPDATE - uppdatera kolumner med matchad post specificerad av SET ....
  • WHEN NOT MATCHED - åtgärder som ska WHEN NOT MATCHED när matchning inte finns i targetTable
  • WHEN NOT MATCHED BY SOURCE - åtgärder som ska vidtas när matchning inte finns i sourceTable

kommentarer:

Om en specifik åtgärd inte behövs, kan du undvika villkoret, t.ex. att ta bort WHEN NOT MATCHED THEN INSERT förhindrar att poster införs

Sammanfattning uttalande kräver en avslutande semikolon.

restriktioner:

  • WHEN MATCHED tillåter INSERT åtgärder
  • UPDATE åtgärden kan bara uppdatera en rad en gång. Detta innebär att kopplingsvillkoret måste producera unika matchningar.

Slå samman med CTE-källa

WITH SourceTableCTE AS
(
    SELECT * FROM SourceTable
)
MERGE  
 TargetTable AS target
USING SourceTableCTE AS source  
ON (target.PKID = source.PKID)
WHEN MATCHED THEN     
    UPDATE SET target.ColumnA = source.ColumnA
WHEN NOT MATCHED THEN
    INSERT (ColumnA) VALUES (Source.ColumnA);

MERGE med hjälp av Derived Source Table

MERGE INTO TargetTable  AS Target  
USING (VALUES (1,'Value1'), (2, 'Value2'), (3,'Value3'))  
       AS Source (PKID, ColumnA)  
ON Target.PKID = Source.PKID 
WHEN MATCHED THEN 
    UPDATE SET target.ColumnA= source.ColumnA
WHEN NOT MATCHED THEN
    INSERT (PKID, ColumnA) VALUES (Source.PKID, Source.ColumnA);

Sammanställningsexempel - Synkronisera käll- och måltabell

För att illustrera MERGE-uttalandet, överväg följande två tabeller -

  1. dbo.Product : Denna tabell innehåller information om produkten som företaget för närvarande säljer

  2. dbo.ProductNew : Denna tabell innehåller information om produkten som företaget kommer att sälja i framtiden.

Följande T-SQL skapar och fyller dessa två tabeller

IF OBJECT_id(N'dbo.Product',N'U') IS NOT NULL 
DROP TABLE dbo.Product
GO

CREATE TABLE dbo.Product (
ProductID INT PRIMARY KEY,
ProductName NVARCHAR(64),
PRICE MONEY
)

IF OBJECT_id(N'dbo.ProductNew',N'U') IS NOT NULL 
DROP TABLE dbo.ProductNew
GO

CREATE TABLE dbo.ProductNew (
ProductID INT PRIMARY KEY,
ProductName NVARCHAR(64),
PRICE MONEY
)

INSERT INTO dbo.Product VALUES(1,'IPod',300)
,(2,'IPhone',400)
,(3,'ChromeCast',100)
,(4,'raspberry pi',50)

INSERT INTO dbo.ProductNew VALUES(1,'Asus Notebook',300)
,(2,'Hp Notebook',400)
,(3,'Dell Notebook',100)
,(4,'raspberry pi',50)

Anta nu att vi vill synkronisera dbo.Product-måltabellen med dbo.ProductNew-tabellen. Här är kriteriet för denna uppgift:

  1. Produkt som finns i både dbo.ProductNew-källtabellen och dbo.Product-måltabellen uppdateras i dbo.Product-måltabellen med nya nya produkter.

  2. Varje produkt i dbo.ProductNy källtabellen som inte finns i dob.Product-måltabellen införs i dbo.Product-måltabellen.

  3. Alla produkter i tabellen dbo.Product-mål som inte finns i dbo.ProductNew-källtabellen måste tas bort från dbo.Product-måltabellen. Här är MERGE-uttalandet för att utföra denna uppgift.

MERGE dbo.Product AS SourceTbl 
USING dbo.ProductNew AS TargetTbl ON (SourceTbl.ProductID = TargetTbl.ProductID)
WHEN MATCHED 
            AND SourceTbl.ProductName <> TargetTbl.ProductName
            OR SourceTbl.Price <> TargetTbl.Price
    THEN UPDATE SET SourceTbl.ProductName = TargetTbl.ProductName,
                SourceTbl.Price = TargetTbl.Price
WHEN NOT MATCHED 
    THEN INSERT (ProductID, ProductName, Price)
         VALUES (TargetTbl.ProductID, TargetTbl.ProductName, TargetTbl.Price)
WHEN NOT MATCHED BY SOURCE 
    THEN DELETE
OUTPUT $action, INSERTED.*, DELETED.*;

Obs: Semikolon måste vara närvarande i slutet av MERGE-uttalandet. ange bildbeskrivning här

Slå ihop med undantag

Använd UNDANTAG för att förhindra uppdateringar av oförändrade poster

MERGE TargetTable targ
USING SourceTable AS src
    ON src.id = targ.id
WHEN MATCHED
    AND EXISTS (
        SELECT src.field
        EXCEPT
        SELECT targ.field
        )
    THEN
        UPDATE
        SET field = src.field
WHEN NOT MATCHED BY TARGET
    THEN
        INSERT (
            id
            ,field
            )
        VALUES (
            src.id
            ,src.field
            )
WHEN NOT MATCHED BY SOURCE
    THEN
        DELETE;


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow