Szukaj…


Wprowadzenie

Począwszy od SQL Server 2008 można wykonywać operacje wstawiania, aktualizacji lub usuwania w pojedynczej instrukcji za pomocą instrukcji MERGE.

Instrukcja MERGE pozwala dołączyć do źródła danych z docelową tabelą lub widokiem, a następnie wykonać wiele działań przeciwko celowi na podstawie wyników tego połączenia.

Składnia

  • Zgodnie z MSDN - https://msdn.microsoft.com/en-us/library/bb510625.aspx [Z <wyrażenie_tabela_tabeli> [, ... n]] POŁĄCZ [TOP (wyrażenie) [PERCENT]] [INTO] < tabela_cel> TARGET] [AND <clause_search_condition>] THEN <merge_not_matched>] [GDY NIE DOPASOWANE PRZEZ ŹRÓDŁO [ORAZ <clause_search_condition>] THEN <merge_matched>] [... n] [<putput_clause>] [OPTION (<query_hint>]. ..n])]; <target_table> :: = {[nazwa_bazy_danych. nazwa_schematu. | nazwa_schematu. ] target_table} <merge_hint> :: = {{[<table_hint_limited> [, ... n]] [[,] INDEX (index_val [, ... n])]}} <table_source> :: = {table_or_view_name [ [AS] table_alias] [<tablesample_clause>] [WITH (table_hint [[,] ... n])] | rowset_function [[AS] table_alias] [(bulk_column_alias [, ... n])] | user_defined_function [[AS] table_alias] | OPENXML <klucz open_ml> pochodna_tabela [AS] tabela_alias [(kolumna_alias [, ... n])] | <joined_table> | <pivoted_table> | <podprzedstawiona_tabela>} <merge_search_condition> :: = <search_condition> <merge_matched> :: = {UPDATE SET <set_clause> | DELETE} <klucz_zestawu> :: = SET {nazwa_kolumny = {wyrażenie | DOMYŚLNE | NULL} | {udt_column_name. {{property_name = wyrażenie | nazwa_pola = wyrażenie} | nazwa_metody (argument [, ... n])}} | nazwa_kolumny {.WRITE (wyrażenie, @Offset, @Length)} | @variable = wyrażenie | @variable = column = expression | nazwa_kolumny {+ = | - = | * = | / = | % = | & = | ^ = | | =} wyrażenie | @variable {+ = | - = | * = | / = | % = | & = | ^ = | | =} wyrażenie | @variable = kolumna {+ = | - = | * = | / = | % = | & = | ^ = | | =} wyrażenie} [, ... n] <merge_not_matched> :: = {INSERT [(lista_kolumn)] {WARTOŚCI (lista_wartości) | WARTOŚCI DOMYŚLNE}} <clause_search_condition> :: = <search_condition> :: = {[NOT] | (<warunek_wyszukiwania>)} [{AND | LUB} [NIE] {| (<warunek_wyszukiwania>)}] [, ... n] :: = {wyrażenie {= | <> | ! = |

    | > = | ! > | <| <= | ! <} wyrażenie | wyrażenie_łańcuchowe [NIE] LIKE wyrażenie_łańcuchowe [ESCAPE 'escape_character'] | wyrażenie [NIE] MIĘDZY wyrażeniem I wyrażeniem | wyrażenie IS [NOT] NULL | ZAWIERA ({kolumna | *}, „<zawiera warunek_wyszukiwania>”) | FREETEXT ({kolumna | *}, „freetext_string”) | wyrażenie [NOT] IN (podzapytanie | wyrażenie [, ... n]) | wyrażenie {= | <> | ! = | | > = | ! > | <| <= | ! <} {WSZYSTKO | NIEKTÓRE | DOWOLNY} (podzapytanie) | ISTNIEJE (podzapytanie)} <klucz_wyjściowy> :: = {[WYJŚCIE <lista_wybranych_dml> INTO {@ zmienna_tabeli | tabela_wyjściowa} [(lista_kolumn)]] [WYJŚCIE <lista_wybranych_dml>]} <lista_wybranych_dml> :: = {<nazwa_kolumny> | scalar_expression} [[AS] identyfikator_kolumny kolumny] [, ... n] <nazwa_kolumny> :: = {USUNIĘTO | WSTAWIONE | from_table_name}. {* | nazwa_kolumny} | $ akcja

Uwagi

Wykonuje operacje wstawiania, aktualizacji lub usuwania tabeli docelowej na podstawie wyników łączenia z tabelą źródłową. Na przykład możesz zsynchronizować dwie tabele, wstawiając, aktualizując lub usuwając wiersze w jednej tabeli na podstawie różnic znalezionych w drugiej tabeli.

ŁĄCZ, aby wstawić / zaktualizować / usunąć

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

Opis:

  • MERGE INTO targetTable do tabeli MERGE INTO targetTable - tabela do modyfikacji
  • USING sourceTable - źródło danych (może to być tabela lub widok lub funkcja wyceniana w tabeli)
  • ON ... - warunek dołączenia między targetTable i sourceTable .
  • WHEN MATCHED - działania, które należy podjąć po znalezieniu dopasowania
    • AND (targetTable.PKID > 100) - dodatkowe warunki, które muszą zostać spełnione, aby można było podjąć działanie
  • THEN DELETE - usuń dopasowany rekord z targetTable
  • THEN UPDATE - zaktualizuj kolumny dopasowanego rekordu określonego przez SET ....
  • WHEN NOT MATCHED - działania, które należy podjąć, gdy dopasowanie nie zostanie znalezione w targetTable
  • WHEN NOT MATCHED BY SOURCE - działania, które należy podjąć, gdy dopasowanie nie zostanie znalezione w sourceTable

Komentarze:

Jeśli określone działanie nie jest potrzebne, pomiń warunek, np. Usunięcie WHEN NOT MATCHED THEN INSERT zapobiegnie wstawianiu rekordów

Instrukcja scalania wymaga średnika kończącego.

Ograniczenia:

  • WHEN MATCHED nie zezwala na INSERT
  • UPDATE może zaktualizować wiersz tylko raz. Oznacza to, że warunek łączenia musi dawać unikalne dopasowania.

Scal za pomocą źródła CTE

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

POŁĄCZ, używając pochodnej tabeli źródłowej

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

Przykład scalania - Synchronizacja tabeli źródłowej i docelowej

Aby zilustrować instrukcję MERGE, rozważ następujące dwie tabele:

  1. dbo.Produkt : Ta tabela zawiera informacje o produkcie, który firma obecnie sprzedaje

  2. dbo.ProductNew : Ta tabela zawiera informacje o produkcie, który firma będzie sprzedawać w przyszłości.

Poniższy T-SQL utworzy i zapełni te dwie tabele

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)

Załóżmy teraz, że chcemy zsynchronizować tabelę docelową dbo.Product z tabelą dbo.ProductNew. Oto kryterium tego zadania:

  1. Produkty istniejące zarówno w tabeli źródłowej dbo.ProductNew, jak i tabeli docelowej dbo.Product są aktualizowane w tabeli docelowej dbo.Product o nowe nowe produkty.

  2. Każdy produkt w tabeli źródłowej dbo.ProductNew, który nie istnieje w tabeli docelowej dob.Product, jest wstawiany do tabeli docelowej dbo.Product.

  3. Każdy produkt w tabeli docelowej dbo.Product, który nie istnieje w tabeli źródłowej dbo.ProductNew, musi zostać usunięty z tabeli docelowej dbo.Product. Oto instrukcja MERGE do wykonania tego zadania.

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.*;

Uwaga: średnik musi znajdować się na końcu instrukcji MERGE. wprowadź opis zdjęcia tutaj

Scal za pomocą WYJĄTKU

Użyj WYJĄTKU, aby zapobiec aktualizacjom niezmienionych rekordów

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow