Sdílet prostřednictvím


MERGE (Transact-SQL)

Platí na:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse Analytics (dedicated SQL pool only)SQL databáze v Microsoft FabricSklad v Microsoft Fabric

Příkaz MERGE spustí operace vložení, aktualizace nebo odstranění cílové tabulky z výsledků spojení se zdrojovou tabulkou. Můžete například synchronizovat dvě tabulky vložením, aktualizací nebo odstraněním řádků v jedné tabulce na základě rozdílů nalezených v druhé tabulce.

Tento článek obsahuje různé syntaxe, argumenty, poznámky, oprávnění a příklady na základě vybrané verze produktu. V rozevíracím seznamu verzí vyberte požadovanou verzi produktu.

Note

Ve službě Fabric Data Warehouse MERGE je ve verzi Preview.

Transact-SQL konvence syntaxe

Syntax

Syntaxe pro SQL Server a Azure SQL Database:

[ WITH <common_table_expression> [,...n] ]
MERGE
    [ TOP ( expression ) [ PERCENT ] ]
    [ INTO ] <target_table> [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]
    USING <table_source> [ [ AS ] table_alias ]
    ON <merge_search_condition>
    [ WHEN MATCHED [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
        THEN <merge_not_matched> ]
    [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ <output_clause> ]
    [ OPTION ( <query_hint> [ ,...n ] ) ]
;

<target_table> ::=
{
    [ database_name . schema_name . | schema_name . ] [ [ AS ] target_table ]
    | @variable [ [ AS ] target_table ]
    | common_table_expression_name [ [ AS ] target_table ]
}

<merge_hint>::=
{
    { [ <table_hint_limited> [ ,...n ] ]
    [ [ , ] { INDEX ( index_val [ ,...n ] ) | INDEX = index_val }]
    }
}

<merge_search_condition> ::=
    <search_condition>

<merge_matched>::=
    { UPDATE SET <set_clause> | DELETE }

<merge_not_matched>::=
{
    INSERT [ ( column_list ) ]
        { VALUES ( values_list )
        | DEFAULT VALUES }
}

<clause_search_condition> ::=
    <search_condition>

Syntaxe pro Azure Synapse Analytics, datový sklad prostředků infrastruktury:

[ WITH <common_table_expression> [,...n] ]
MERGE
    [ INTO ] <target_table> [ [ AS ] table_alias ]
    USING <table_source> [ [ AS ] table_alias ]
    ON <merge_search_condition>
    [ WHEN MATCHED [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
        THEN <merge_not_matched> ]
    [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
        THEN <merge_matched> ] [ ...n ]
    [ OPTION ( <query_hint> [ ,...n ] ) ]
;  -- The semi-colon is required, or the query will return a syntax error.

<target_table> ::=
{
    [ database_name . schema_name . | schema_name . ]
  target_table
}

<merge_search_condition> ::=
    <search_condition>

<merge_matched>::=
    { UPDATE SET <set_clause> | DELETE }

<merge_not_matched>::=
{
    INSERT [ ( column_list ) ]
        VALUES ( values_list )
}

<clause_search_condition> ::=
    <search_condition>

Arguments

S <common_table_expression>

Určuje dočasnou pojmenovanou sadu výsledků nebo zobrazení, označovanou také jako běžný výraz tabulky, která je definována v rámci rozsahu MERGE příkazu. Sada výsledků je odvozena z jednoduchého dotazu a odkazuje na příkaz MERGE . Další informace najdete v tématu WITH common_table_expression (Transact-SQL).

TOP ( výraz ) [ PERCENT ]

Určuje počet nebo procento ovlivněných řádků. výraz může být číslo nebo procento řádků. Řádky odkazované ve výrazu TOP nejsou uspořádány v žádném pořadí. Další informace naleznete v tématu TOP (Transact-SQL).

Klauzule TOP platí po celé zdrojové tabulce a celém spojení cílové tabulky a spojených řádcích, které nemají nárok na akci vložení, aktualizace nebo odstranění. Klauzule TOP dále snižuje počet spojených řádků na zadanou hodnotu. Tyto akce (vložení, aktualizace nebo odstranění) se vztahují na zbývající spojené řádky v neuspořádaném způsobu. To znamená, že řádky nejsou rozdělené mezi akce definované v WHEN klauzulích. Například zadání TOP (10) ovlivňuje 10 řádků. Z těchto řádků může být 7 aktualizováno a vloženo 3, nebo 1 může být odstraněno, 5 aktualizováno a 4 vloženo atd.

Bez filtrů ve zdrojové tabulce MERGE může příkaz provést prohledávání tabulek nebo clusterovanou kontrolu indexu ve zdrojové tabulce a také prohledávání tabulek nebo vyhledávání clusterovaných indexů cílové tabulky. Výkon vstupně-výstupních operací je proto někdy ovlivněn i při použití TOP klauzule k úpravě velké tabulky vytvořením více dávek. V tomto scénáři je důležité zajistit, aby všechny následné dávky cílily na nové řádky.

database_name

Název databáze, ve které se nachází target_table .

schema_name

Název schématu, do kterého target_table patří.

target_table

Tabulka nebo zobrazení, ze <table_source> kterého se řádky dat shodují na <clause_search_condition>základě . target_table je cílem operací vložení, aktualizace nebo odstranění určených WHEN klauzulí MERGE příkazu.

Pokud je target_table zobrazení, musí všechny akce s ním splňovat podmínky pro aktualizaci zobrazení. Další informace naleznete v tématu Úprava dat prostřednictvím zobrazení.

target_table nemůže být vzdálená tabulka. target_table nemůže mít definovaná žádná pravidla. target_table nemůže být tabulka optimalizovaná pro paměť.

Nápovědy lze zadat jako <merge_hint>.

<merge_hint> Azure Synapse Analytics nepodporuje.

[ JAKO ] table_alias

Alternativní název pro odkazování na tabulku pro target_table.

POUŽÍVÁM <table_source>

Určuje zdroj dat, který odpovídá řádkům dat v target_table na <merge_search_condition>základě . Výsledek této shody určuje akce, které mají provádět WHEN klauzule MERGE příkazu. <table_source> může být vzdálená tabulka nebo odvozená tabulka, která přistupuje ke vzdáleným tabulkám.

<table_source> může být odvozená tabulka, která používá konstruktor hodnot tabulky Transact-SQL k vytvoření tabulky zadáním více řádků.

<table_source> může být odvozená tabulka, která slouží SELECT ... UNION ALL k vytvoření tabulky zadáním více řádků.

[ JAKO ] table_alias

Alternativní název pro odkaz na tabulku pro table_source.

Další informace o syntaxi a argumentech této klauzule naleznete v tématu FROM (Transact-SQL).

ZAPNUTO <merge_search_condition>

Určuje podmínky, pro které <table_source> se spojí s target_table , aby bylo možné určit, kde se shodují.

Caution

Je důležité zadat pouze sloupce z cílové tabulky, které se mají použít pro odpovídající účely. To znamená, že zadejte sloupce z cílové tabulky, které se porovnávají s odpovídajícím sloupcem zdrojové tabulky. Nepokoušejte se zlepšit výkon dotazů filtrováním řádků v cílové tabulce v ON klauzuli, například zadáním AND NOT target_table.column_x = value. Tím se můžou vrátit neočekávané a nesprávné výsledky.

PO POROVNÁNÍ PAK <merge_matched>

Určuje, že všechny řádky *target_table, které odpovídají řádkům vráceným <table_source> ON <merge_search_condition>a splňují všechny další hledané podmínky, se aktualizují nebo odstraní podle <merge_matched> klauzule.

Příkaz MERGE může mít maximálně dvě WHEN MATCHED klauzule. Pokud jsou zadány dvě klauzule, musí být první klauzule doprovázena AND<search_condition> klauzulí. U každého daného řádku se druhá WHEN MATCHED klauzule použije jenom v případě, že první není. Pokud existují dvě WHEN MATCHED klauzule, jedna musí zadat UPDATE akci a jedna musí zadat DELETE akci. Při UPDATE zadání v <merge_matched> klauzuli a více než jeden řádek <table_source> odpovídá řádku v target_table na <merge_search_condition>základě , SQL Server vrátí chybu. Příkaz MERGE nemůže aktualizovat stejný řádek více než jednou nebo aktualizovat a odstranit stejný řádek.

KDYŽ SE NESHODUJE [ PODLE CÍLE ] PAK <merge_not_matched>

Určuje, že je řádek vložen do target_table pro každý řádek vrácený <table_source> ON <merge_search_condition> , který neodpovídá řádku v target_table, ale splňuje další podmínku hledání, pokud je k dispozici. Hodnoty, které se mají vložit, jsou určeny <merge_not_matched> klauzulí. Příkaz MERGE může mít pouze jednu WHEN NOT MATCHED [ BY TARGET ] klauzuli.

POKUD ZDROJ NEODPOVÍDÁ <, pak merge_matched>

Určuje, že všechny řádky *target_table, které neodpovídají řádkům vráceným <table_source> ON <merge_search_condition>a které splňují všechny další podmínky hledání, se aktualizují nebo odstraní podle <merge_matched> klauzule.

Příkaz MERGE může mít maximálně dvě WHEN NOT MATCHED BY SOURCE klauzule. Pokud jsou zadány dvě klauzule, musí být první klauzule doprovázena AND<clause_search_condition> klauzulí. U každého daného řádku se druhá WHEN NOT MATCHED BY SOURCE klauzule použije jenom v případě, že první není. Pokud existují dvě WHEN NOT MATCHED BY SOURCE klauzule, musí jedna zadat UPDATE akci a jedna musí zadat DELETE akci. Odkazovat lze <clause_search_condition>pouze na sloupce z cílové tabulky .

Pokud sloupce ve zdrojové tabulce nevrátí <table_source>žádné řádky, nebudou mít přístup. Pokud akce aktualizace nebo odstranění zadaná v <merge_matched> klauzuli odkazuje na sloupce ve zdrojové tabulce, vrátí se chyba 207 (Neplatný název sloupce). Klauzule WHEN NOT MATCHED BY SOURCE THEN UPDATE SET TargetTable.Col1 = SourceTable.Col1 může například způsobit selhání příkazu, protože Col1 ve zdrojové tabulce je nepřístupná.

A clause_search_condition <>

Určuje jakoukoli platnou podmínku hledání. Další informace naleznete v tématu Podmínka hledání (Transact-SQL).

<table_hint_limited>

Určuje jednu nebo více tipů tabulky, které se mají použít u cílové tabulky pro každou z akcí vložení, aktualizace nebo odstranění provedených příkazem MERGE . Klíčové WITH slovo a závorky jsou povinné.

NOLOCK a READUNCOMMITTED nejsou povoleny. Další informace o nápovědě k tabulce naleznete v tématu Nápověda k tabulce (Transact-SQL).

Určení nápovědy TABLOCK pro tabulku, která je cílem INSERT příkazu, má stejný účinek jako určení nápovědy TABLOCKX . Na tabulce se převezme exkluzivní zámek. Pokud je zadána funkce FORCESEEK, použije se na implicitní instanci cílové tabulky spojené se zdrojovou tabulkou.

Caution

Zadání READPAST může vést k WHEN NOT MATCHED [ BY TARGET ] THEN INSERT operacímINSERT, které porušují UNIQUE omezení.

INDEX ( index_val [ ,... n ] )

Určuje název nebo ID jednoho nebo více indexů v cílové tabulce pro implicitní spojení se zdrojovou tabulkou. Další informace naleznete v části Tipy pro tabulku (Transact-SQL).

<output_clause>

Vrátí řádek pro každý řádek v target_table , který je aktualizovaný, vložený nebo odstraněný, v žádném konkrétním pořadí. $action lze zadat ve výstupní klauzuli. $action je sloupec typu nvarchar(10), který vrátí jednu ze tří hodnot pro každý řádek: INSERT, UPDATEnebo DELETE, podle akce provedené na daném řádku. Tato OUTPUT klauzule představuje doporučený způsob, jak dotazovat nebo spočítat řádky ovlivněné klauzulí MERGE. Další informace o argumentech a chování této klauzule naleznete v tématu OUTPUT klauzule (Transact-SQL).

OPTION ( <query_hint> [ ,... n ] )

Určuje, že se nápovědy optimalizátoru používají k přizpůsobení způsobu, jakým databázový stroj zpracovává příkaz. Další informace naleznete v tématu Nápovědy k dotazům (Transact-SQL).

<merge_matched>

Určuje akci aktualizace nebo odstranění použitou na všechny řádky target_table , které neodpovídají řádkům vráceným <table_source> ON <merge_search_condition>a které splňují všechny další podmínky hledání.

SET_CLAUSE UPDATE SET <>

Určuje seznam názvů sloupců nebo proměnných, které se mají aktualizovat v cílové tabulce, a hodnoty, se kterými se mají aktualizovat.

Další informace o argumentech této klauzule naleznete v tématu UPDATE (Transact-SQL). Nastavení proměnné na stejnou hodnotu jako sloupec se nepodporuje.

DELETE

Určuje, že se odstraní řádky odpovídající řádkům v target_table .

<merge_not_matched>

Určuje hodnoty, které se mají vložit do cílové tabulky.

( column_list )

Seznam jednoho nebo více sloupců cílové tabulky, do které chcete vložit data. Sloupce musí být zadány jako název jedné části nebo jinak MERGE příkaz selže. column_list musí být uzavřeny v závorkách a oddělené čárkami.

HODNOTY ( values_list )

Čárkami oddělený seznam konstant, proměnných nebo výrazů, které vracejí hodnoty, které se mají vložit do cílové tabulky. Výrazy nemohou obsahovat EXECUTE příkaz.

VÝCHOZÍ HODNOTY

Vynutí vložený řádek, aby obsahoval výchozí hodnoty definované pro každý sloupec.

Další informace o této klauzuli naleznete v tématu INSERT (Transact-SQL).

<search_condition>

Určuje podmínky hledání, které se mají zadat <merge_search_condition> nebo <clause_search_condition>. Další informace o argumentech této klauzule najdete v tématu Podmínka hledání (Transact-SQL).

<grafové vyhledávání>

Určuje vzor shody grafu. Další informace o argumentech této klauzule naleznete v tématu POZVYHLEDAT (Transact-SQL).

Remarks

Podmíněné chování popsané pro MERGE příkaz funguje nejlépe, když obě tabulky mají složitou kombinaci shodných charakteristik. Například vložení řádku, pokud neexistuje, nebo aktualizace řádku, pokud odpovídá. Když jednoduše aktualizujete jednu tabulku na základě řádků jiné tabulky, vylepšete výkon a škálovatelnost pomocí příkazů INSERTUPDATEa DELETE příkazů . Například:

INSERT tbl_A (col, col2)
SELECT col, col2
FROM tbl_B
WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);

Musí být zadána alespoň jedna ze tří MATCHED klauzulí, ale lze je zadat v libovolném pořadí. Proměnnou nelze aktualizovat více než jednou ve stejné MATCHED klauzuli.

Jakákoli akce vložení, aktualizace nebo odstranění zadaná v cílové tabulce pomocí MERGE příkazu jsou omezena všemi omezeními definovanými v ní, včetně jakýchkoli kaskádových omezení referenční integrity. Pokud IGNORE_DUP_KEY je ON pro všechny jedinečné indexy v cílové tabulce, MERGE ignoruje toto nastavení.

Příkaz MERGE vyžaduje středník (;) jako ukončovací znak příkazu. Chyba 10713 je vyvolána při MERGE spuštění příkazu bez ukončovací funkce.

Při použití po MERGE, @@ROWCOUNT (Transact-SQL) vrátí celkový počet řádků vložených, aktualizovaných a odstraněných do klienta.

MERGE je plně rezervované klíčové slovo, pokud je úroveň kompatibility databáze nastavena 100 na nebo vyšší. Příkaz je k dispozici na úrovni kompatibility obou i databází. Klíčové MERGE slovo však není plně vyhrazeno, pokud je úroveň kompatibility databáze nastavena na 90.10090

Caution

Nepoužívejte tento MERGE příkaz při použití replikace aktualizace ve frontě. Aktivační MERGE událost aktualizace ve frontě není kompatibilní. MERGE Nahraďte příkaz příkazem INSERT a UPDATE příkazy.

Důležité informace o službě Azure Synapse Analytics

Ve službě Azure Synapse Analytics MERGE má příkaz v porovnání s SQL Serverem a službou Azure SQL Database následující rozdíly.

  • Použití MERGE k aktualizaci sloupce distribučního klíče není podporováno v buildech starších než 10.0.17829.0. Pokud nejde pozastavit nebo vynutit upgrade, použijte příkaz ANSI UPDATE FROM ... JOIN jako alternativní řešení, dokud nebude verze 10.0.17829.0.
  • Aktualizace MERGE se implementuje jako dvojice odstranění a vložení. Ovlivněný počet řádků aktualizace MERGE zahrnuje odstraněné a vložené řádky.
  • MERGE...WHEN NOT MATCHED INSERT nepodporuje tabulky se IDENTITY sloupci.
  • Konstruktor hodnot tabulky nelze použít v USING klauzuli zdrojové tabulky. Slouží SELECT ... UNION ALL k vytvoření odvozené zdrojové tabulky s více řádky.
  • Podpora tabulek s různými typy distribuce je popsaná v této tabulce:
KLAUZULE MERGE VE službě Azure Synapse Analytics Podporovaná TARGET distribuční tabulka Podporovaná distribuční tabulka SOURCE Comment
WHEN MATCHED Všechny typy distribuce Všechny typy distribuce
NOT MATCHED BY TARGET HASH Všechny typy distribuce Slouží UPDATE/DELETE FROM...JOIN k synchronizaci dvou tabulek.
NOT MATCHED BY SOURCE Všechny typy distribuce Všechny typy distribuce

Tip

Pokud jako sloupec JOIN používáte distribuční hashovací klíč MERGE a provádíte pouze porovnání rovnosti, můžete vynechat distribuční klíč ze seznamu sloupců v WHEN MATCHED THEN UPDATE SET klauzuli, protože se jedná o redundantní aktualizaci.

V Azure Synapse Analytics MERGE může příkaz na buildech starších než 10.0.17829.0 za určitých podmínek ponechat cílovou tabulku v nekonzistentním stavu s řádky umístěnými v nesprávné distribuci, což v některých případech způsobí, že pozdější dotazy vrátí nesprávné výsledky. K tomuto problému může dojít ve 2 případech:

Scenario Comment
Případ 1
Použití MERGE v distribuované TARGET tabulce HASH, která obsahuje sekundární indexy nebo UNIQUE omezení.
– Opraveno v Synapse SQL 10.0.15563.0 a novějších verzích.
– Pokud SELECT @@VERSION vrátí nižší verzi než 10.0.15563.0, ručně pozastavte fond Synapse SQL a obnovte ho, abyste tuto opravu získali.
– Dokud se na fond Synapse SQL nepoužije oprava, nepoužívejte MERGE příkaz u HASH distribuovaných TARGET tabulek, které mají sekundární indexy nebo UNIQUE omezení.
Případ 2
Použití funkce MERGE k aktualizaci sloupce distribučního klíče distribuované tabulky HASH
– Opraveno v Synapse SQL 10.0.17829.0 a novějších verzích.
– Pokud SELECT @@VERSION vrátí nižší verzi než 10.0.17829.0, ručně pozastavte fond Synapse SQL a obnovte ho, abyste tuto opravu získali.
– Dokud nebude oprava použita ve vašem fondu Synapse SQL, nepoužívejte MERGE příkaz k aktualizaci sloupců distribučního klíče.

Aktualizace v obou scénářích neopravují tabulky, které jsou již ovlivněny předchozím MERGE spuštěním. Pomocí následujících skriptů identifikujte a opravte všechny ovlivněné tabulky ručně.

Pokud chcete zkontrolovat, které HASH distribuované tabulky v databázi můžou být důležité (pokud se používají v dříve uvedených případech), spusťte tento příkaz:

-- Case 1
SELECT a.name,
    c.distribution_policy_desc,
    b.type
FROM sys.tables a
INNER JOIN sys.indexes b
    ON a.object_id = b.object_id
INNER JOIN sys.pdw_table_distribution_properties c
    ON a.object_id = c.object_id
WHERE b.type = 2
    AND c.distribution_policy_desc = 'HASH';

-- Subject to Case 2, if distribution key value is updated in MERGE statement
SELECT a.name,
    c.distribution_policy_desc
FROM sys.tables a
INNER JOIN sys.pdw_table_distribution_properties c
    ON a.object_id = c.object_id
WHERE c.distribution_policy_desc = 'HASH';

Pokud chcete zkontrolovat, jestli je distribuovaná HASH tabulka MERGE ovlivněná případem 1 nebo případem 2, postupujte podle těchto kroků a zkontrolujte, jestli tabulky obsahují řádky v nesprávné distribuci. Pokud no need for repair je vrácena, tato tabulka není ovlivněna.

IF object_id('[check_table_1]', 'U') IS NOT NULL
    DROP TABLE [check_table_1]
GO

IF object_id('[check_table_2]', 'U') IS NOT NULL
    DROP TABLE [check_table_2]
GO

CREATE TABLE [check_table_1]
    WITH (DISTRIBUTION = ROUND_ROBIN) AS

SELECT <DISTRIBUTION_COLUMN> AS x
FROM <MERGE_TABLE>
GROUP BY <DISTRIBUTION_COLUMN>;
GO

CREATE TABLE [check_table_2]
    WITH (DISTRIBUTION = HASH (x)) AS

SELECT x
FROM [check_table_1];
GO

IF NOT EXISTS (
        SELECT TOP 1 *
        FROM (
            SELECT <DISTRIBUTION_COLUMN> AS x
            FROM <MERGE_TABLE>

            EXCEPT

            SELECT x
            FROM [check_table_2]
            ) AS tmp
        )
    SELECT 'no need for repair' AS result
ELSE
    SELECT 'needs repair' AS result
GO

IF object_id('[check_table_1]', 'U') IS NOT NULL
    DROP TABLE [check_table_1]
GO

IF object_id('[check_table_2]', 'U') IS NOT NULL
    DROP TABLE [check_table_2]
GO

Pokud chcete opravit ovlivněné tabulky, spusťte tyto příkazy a zkopírujte všechny řádky ze staré tabulky do nové tabulky.

IF object_id('[repair_table_temp]', 'U') IS NOT NULL
    DROP TABLE [repair_table_temp];
GO

IF object_id('[repair_table]', 'U') IS NOT NULL
    DROP TABLE [repair_table];
GO

CREATE TABLE [repair_table_temp]
    WITH (DISTRIBUTION = ROUND_ROBIN) AS

SELECT *
FROM <MERGE_TABLE>;
GO

-- [repair_table] will hold the repaired table generated from <MERGE_TABLE>
CREATE TABLE [repair_table]
    WITH (DISTRIBUTION = HASH (<DISTRIBUTION_COLUMN>)) AS

SELECT *
FROM [repair_table_temp];
GO

IF object_id('[repair_table_temp]', 'U') IS NOT NULL
    DROP TABLE [repair_table_temp];
GO

Troubleshooting

V určitých scénářích může být výsledkem příkazu chybaMERGE, a to i v případě, CREATE TABLE failed because column <> in table <> exceeds the maximum of 1024 columns. že cílová nebo zdrojová tabulka neobsahuje 1 024 sloupců. Tento scénář může nastat, když jsou splněny některé z následujících podmínek:

  • Více sloupců je zadáno v rámci DELETEoperace , UPDATE SETnebo INSERT uvnitř MERGE (nikoli specifické pro žádnou WHEN [NOT] MATCHED klauzuli)
  • Libovolný sloupec v JOIN podmínce má neclusterovaný index (NCI).
  • Cílová tabulka je HASH distribuovaná

Pokud se tato chyba najde, navrhovaná alternativní řešení jsou následující:

  • Odeberte neclusterovaný index (NCI) ze JOIN sloupců nebo spojujte sloupce bez NCI. Pokud později aktualizujete podkladové tabulky tak, aby zahrnovaly NCI do JOIN sloupců, může být váš MERGE příkaz náchylný k této chybě za běhu. Další informace naleznete v tématu DROP INDEX.
  • Místo příkazu UPDATE, DELETE a INSERT použijte příkazy UPDATE, MERGE a INSERT.

Implementace triggeru

Pro každou akci vložení, aktualizace nebo odstranění zadanou v MERGE příkazu sql Server aktivuje všechny odpovídající AFTER triggery definované v cílové tabulce, ale nezaručuje, jaká akce se má aktivovat jako první nebo poslední. Triggery definované pro stejnou akci dodržují vámi zadané pořadí. Další informace o nastavení pořadí aktivací triggeru najdete v tématu Určení prvního a posledního triggeru.

Pokud má cílová tabulka povolenou INSTEAD aktivační událost OF definovanou pro akci vložení, aktualizace nebo odstranění provedenou příkazem MERGE , musí mít povolenou INSTEAD aktivační událost OF pro všechny akce zadané v MERGE příkazu.

Pokud jsou některé INSTEAD aktivační události OF nebo UPDATE OF INSTEADDELETE definovány v target_table, operace aktualizace nebo odstranění se nespustí. Místo toho se triggery aktivují a vložené a odstraněné tabulky se pak odpovídajícím způsobem naplní.

Pokud jsou některé INSTEAD aktivační události OF INSERT definovány na target_table, operace vložení se neprovádí. Místo toho tabulka vyplní odpovídajícím způsobem.

Note

Na rozdíl od samostatných INSERTpříkazů UPDATEa DELETE příkazů může být počet řádků, které @@ROWCOUNT se projeví uvnitř triggeru, vyšší. Vnitřní @@ROWCOUNT aktivační AFTER událost (bez ohledu na příkazy pro úpravu dat, které trigger zachytí) bude odrážet celkový počet řádků ovlivněných objektem MERGE. Pokud MERGE například příkaz vloží jeden řádek, aktualizuje jeden řádek a odstraní jeden řádek, @@ROWCOUNT bude tři pro každý AFTER trigger, i když je aktivační událost deklarována pouze pro INSERT příkazy.

Permissions

Vyžaduje SELECT oprávnění ke zdrojové tabulce a INSERTUPDATE, nebo DELETE oprávnění k cílové tabulce. Další informace naleznete v části Oprávnění v článcích SELECT (Transact-SQL), INSERT (Transact-SQL), UPDATE (Transact-SQL) a DELETE (Transact-SQL).

Osvědčené postupy indexu

Pomocí příkazu MERGE můžete nahradit jednotlivé příkazy DML jediným příkazem. To může zlepšit výkon dotazů, protože operace se provádějí v rámci jednoho příkazu, a proto minimalizuje počet dat ve zdrojové a cílové tabulce. Zvýšení výkonu ale závisí na tom, že máte správné indexy, spojení a další důležité informace.

Pokud chcete zvýšit výkon příkazu, doporučujeme následující pokyny indexu MERGE :

  • Vytvořte indexy pro usnadnění spojení mezi zdrojem a cílem objektu MERGE:
    • Vytvořte index ve sloupcích spojení ve zdrojové tabulce s klíči, které pokrývají logiku spojení s cílovou tabulkou. Pokud je to možné, měl by být jedinečný.
    • Také vytvořte index ve sloupcích spojení v cílové tabulce. Pokud je to možné, měl by to být jedinečný clusterovaný index.
    • Tyto dva indexy zajišťují řazení dat v tabulkách a jedinečnost pomáhá při porovnávání. Vylepšili jsme výkon dotazů, protože optimalizátor dotazů nemusí provádět další ověřovací zpracování, aby bylo možné vyhledat a aktualizovat duplicitní řádky a další operace řazení, nejsou potřeba.
  • Jako cíl MERGE příkazů nepoužívejte tabulky s jakoukoli formou indexu columnstore. Stejně jako u všech upDATEs můžete dosáhnout lepšího výkonu s indexy columnstore aktualizací fázované tabulky rowstore a provedením dávkového DELETEINSERTa , místo UPDATE nebo MERGE.

Důležité informace o souběžnosti pro merge

Z hlediska uzamčení se liší od diskrétních, MERGE po sobě jdoucích INSERT, UPDATEa DELETE příkazů. MERGE i nadále provádí INSERT, UPDATEa DELETE operace, ale pomocí různých mechanismů uzamykání. Pro některé potřeby aplikace může být efektivnější psát diskrétní INSERTpříkazy UPDATEa DELETE příkazy. Ve velkém měřítku MERGE může docházet ke složitým problémům se souběžností nebo vyžadovat pokročilé řešení potíží. Proto před nasazením do produkčního prostředí důkladně otestujte všechny MERGE příkazy.

MERGE příkazy jsou vhodná náhrada za diskrétní INSERT, UPDATEa DELETE operace v následujících scénářích (ale nikoli pouze v těchto scénářích):

  • Operace ETL zahrnující velké počty řádků se spouštějí v době, kdy se neočekávají jiné souběžné operace* Pokud očekáváte vysokou souběžnost, samostatná INSERTUPDATE, a DELETE logika může fungovat lépe, s méně blokujícími, než je MERGE příkaz.
  • Složité operace zahrnující malé počty řádků a transakce se pravděpodobně po delší dobu nespustí.
  • Složité operace zahrnující tabulky uživatelů, jejichž indexy je možné navrhnout tak, aby zajistily optimální plány provádění, zabránily prohledávání tabulek a vyhledávání ve prospěch prohledávání indexů nebo ideálně hledání indexů.

Další aspekty souběžnosti:

  • V některých scénářích, kdy se očekává, že se jedinečné klíče vkládají a aktualizují pomocí parametru MERGE, a tím se určí, že HOLDLOCK se zabrání porušení jedinečných klíčů. HOLDLOCK je synonymem pro SERIALIZABLE úroveň izolace transakcí, která neumožňuje jiným souběžným transakcím upravovat data, která tato transakce přečetla. SERIALIZABLE je nejbezpečnější úroveň izolace, ale poskytuje nejnižší souběžnost s jinými transakcemi, které uchovávají zámky na rozsahech dat, aby se zabránilo vkládání nebo aktualizaci přízrakových řádků v průběhu čtení. Další informace naleznete HOLDLOCKv tématu Nápověda k tabulce a SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

Osvědčené postupy PRO JOIN

Pokud chcete zvýšit výkon MERGE prohlášení a zajistit, aby byly získány správné výsledky, doporučujeme následující pokyny pro spojení:

  • V klauzuli zadejte pouze podmínky ON <merge_search_condition> hledání, které určují kritéria pro porovnávání dat ve zdrojových a cílových tabulkách. To znamená, že zadejte pouze sloupce z cílové tabulky, které se porovnávají s odpovídajícími sloupci zdrojové tabulky.
  • Nezahrnujte porovnání s jinými hodnotami, jako je konstanta.

Pokud chcete vyfiltrovat řádky ze zdrojových nebo cílových tabulek, použijte jednu z následujících metod.

  • Zadejte podmínku hledání pro filtrování řádků v příslušné WHEN klauzuli. Například WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT....
  • Definujte zobrazení zdroje nebo cíle, které vrací filtrované řádky a odkazují na zobrazení jako zdrojovou nebo cílovou tabulku. Pokud je zobrazení definované v cílové tabulce, musí všechny akce proti ní splňovat podmínky pro aktualizaci zobrazení. Další informace o aktualizaci dat pomocí zobrazení naleznete v tématu Úprava dat prostřednictvím zobrazení.
  • WITH <common table expression> Pomocí klauzule můžete vyfiltrovat řádky ze zdrojových nebo cílových tabulek. Tato metoda je podobná zadání dalších kritérií hledání v ON klauzuli a může vést k nesprávným výsledkům. Doporučujeme, abyste se před implementací této metody vyhnuli nebo důkladně testovali.

Operace spojení v příkazu MERGE je optimalizovaná stejným způsobem jako spojení v SELECT příkazu. To znamená, že když SQL Server zpracovává spojení, optimalizátor dotazů zvolí nejúčinnější metodu (z několika možností) zpracování spojení. Pokud zdroj a cíl mají podobnou velikost a pokyny indexu popsané dříve se použijí u zdrojových a cílových tabulek, je operátor sloučení spojení nejúčinnějším plánem dotazu. Důvodem je to, že obě tabulky se kontrolují jednou a není potřeba data seřadit. Pokud je zdroj menší než cílová tabulka, je vhodnější operátor vnořených smyček.

Použití konkrétního spojení můžete vynutit zadáním OPTION (<query_hint>) klauzule v MERGE příkazu. Doporučujeme nepoužívat spojení hash jako nápovědu dotazu pro MERGE příkazy, protože tento typ spojení nepoužívá indexy.

Osvědčené postupy pro parametrizaci

Pokud se SELECTpříkaz , INSERT, UPDATEnebo DELETE příkaz spustí bez parametrů, sql Server optimalizátor dotazů může zvolit parametrizaci příkazu interně. To znamená, že všechny hodnoty literálu obsažené v dotazu se nahradí parametry. Například příkaz INSERT dbo.MyTable (Col1, Col2) VALUES (1, 10)může být implementován interně jako INSERT dbo.MyTable (Col1, Col2) VALUES (@p1, @p2). Tento proces, který se nazývá jednoduchá parametrizace, zvyšuje schopnost relačního modulu odpovídat novým příkazům SQL se stávajícími dříve kompilovanými plány provádění. Výkon dotazů se může zlepšit, protože se snižuje frekvence kompilací dotazů a rekompilace. Optimalizátor dotazů nepoužije jednoduchý proces parametrizace na MERGE příkazy. Proto příkazy, které obsahují hodnoty literálů, nemusí provádět a jednotlivé , nebo MERGE příkazy, INSERT protože nový plán je zkompilován při UPDATE každém spuštění DELETEpříkazu.MERGE

Pokud chcete zvýšit výkon dotazů, doporučujeme následující pokyny pro parametrizaci:

  • Parametrizovat všechny hodnoty literálů ON <merge_search_condition> v klauzuli a v WHEN klauzulích MERGE příkazu. Příkaz můžete například začlenit MERGE do uložené procedury a nahradit hodnoty literálu odpovídajícími vstupními parametry.
  • Pokud příkaz nejde parametrizovat, vytvořte průvodce plánem typu TEMPLATE a v průvodci plánem zadejte nápovědu PARAMETERIZATION FORCED dotazu. Další informace naleznete v tématu Určení chování parametrizace dotazu pomocí průvodců plánem.
  • Pokud MERGE jsou příkazy spouštěny často v databázi, zvažte nastavení PARAMETERIZATION možnosti databáze na FORCED. Při nastavování této možnosti buďte opatrní. Tato PARAMETERIZATION možnost je nastavení na úrovni databáze a ovlivňuje způsob zpracování všech dotazů na databázi. Další informace naleznete v tématu Vynucené parametrizace.
  • Jako novější a jednodušší alternativu k průvodcům plánování zvažte podobnou strategii s radami úložiště dotazů. Další informace najdete v části Tipy pro úložiště dotazů.

Osvědčené postupy pro top klauzule

MERGE V příkazu TOP klauzule určuje počet nebo procento řádků, které jsou ovlivněny po spojení zdrojové tabulky a cílové tabulky, a po odebrání řádků, které nemají nárok na akci vložení, aktualizace nebo odstranění. Klauzule TOP dále snižuje počet spojených řádků na zadanou hodnotu a akce vložení, aktualizace nebo odstranění se použijí na zbývající spojené řádky v neuspořádaném stylu. To znamená, že řádky nejsou rozdělené mezi akce definované v WHEN klauzulích. Například zadání TOP (10) má vliv na 10 řádků; z těchto řádků může být aktualizováno 7 a 3 vloženo, nebo může být odstraněno 1, 5 aktualizováno a 4 vloženo atd.

Běžně se používá TOP klauzule k provádění operací jazyka DML (Data Manipulat Language) u velké tabulky v dávkách. Při použití TOP klauzule v MERGE příkazu pro tento účel je důležité pochopit následující důsledky.

  • Může to mít vliv na výkon vstupně-výstupních operací.

    Příkaz MERGE provede úplnou kontrolu tabulky zdrojových i cílových tabulek. Rozdělení operace na dávky snižuje počet operací zápisu provedených v dávce; Každá dávka však provede úplnou kontrolu zdrojové a cílové tabulky. Výsledná aktivita čtení může ovlivnit výkon dotazu a další souběžné aktivity v tabulkách.

  • Může dojít k nesprávným výsledkům.

    Je důležité zajistit, aby všechny následné dávky cílily na nové řádky nebo nežádoucí chování, jako je nesprávné vkládání duplicitních řádků do cílové tabulky, může dojít. K tomu může dojít, když zdrojová tabulka obsahuje řádek, který nebyl v cílové dávce, ale byl v celkové cílové tabulce. Zajištění správných výsledků:

    • ON Pomocí klauzule určete, které zdrojové řádky mají vliv na existující cílové řádky a které jsou skutečně nové.
    • Pomocí další podmínky v WHEN MATCHED klauzuli určete, jestli cílový řádek již byl aktualizován předchozí dávkou.
    • Pomocí další podmínky v WHEN MATCHED klauzuli a SET logice ověřte, že stejný řádek nelze aktualizovat dvakrát.

Vzhledem k tomu, že TOP klauzule se použije pouze po použití těchto klauzulí, každé spuštění buď vloží jeden skutečně nesouvisený řádek, nebo aktualizuje jeden existující řádek.

Osvědčené postupy hromadného načítání

Příkaz MERGE lze použít k efektivnímu hromadnému načtení dat ze zdrojového datového souboru do cílové tabulky zadáním OPENROWSET(BULK...) klauzule jako zdroje tabulky. Tímto způsobem se celý soubor zpracuje v jedné dávce.

Pokud chcete zlepšit výkon procesu hromadné korespondence, doporučujeme následující pokyny:

  • Vytvořte clusterovaný index ve sloupcích spojení v cílové tabulce.

  • Během hromadného načtení MERGEzakažte jiné nevýznamné neclusterované indexy v cílové tabulce , povolte je potom. To je běžné a užitečné pro noční hromadné operace s daty.

  • ORDER UNIQUE Pomocí a tipů v OPENROWSET(BULK...) klauzuli určete, jak se zdrojový datový soubor seřadí.

    Ve výchozím nastavení hromadná operace předpokládá, že datový soubor není seřazený. Proto je důležité, aby zdrojová data byla seřazena podle clusterovaného indexu v cílové tabulce a aby ORDER optimalizátor dotazů mohl vygenerovat efektivnější plán dotazů. Rady se ověřují za běhu; Pokud datový proud neodpovídá zadaným tipům, vyvolá se chyba.

Tyto pokyny zajišťují, že klíče spojení jsou jedinečné a pořadí řazení dat ve zdrojovém souboru odpovídá cílové tabulce. Vylepšili jsme výkon dotazů, protože další operace řazení nejsou nutné a nepotřebné kopie dat se nevyžadují.

Měření a diagnostika výkonu sloučení

K dispozici jsou následující funkce, které vám pomůžou při měření a diagnostice výkonu MERGE prohlášení.

Examples

A. Použití funkce MERGE k provádění operací INSERT a UPDATE v tabulce v jednom příkazu

Běžným scénářem je aktualizace jednoho nebo více sloupců v tabulce, pokud existuje odpovídající řádek. Pokud odpovídající řádek neexistuje, vložte data jako nový řádek. Oba scénáře obvykle provedete předáním parametrů uložené proceduře, která obsahuje příslušné UPDATE příkazy a INSERT příkazy. Pomocí příkazu MERGE můžete provádět oba úkoly v jednom příkazu. Následující příklad ukazuje uloženou proceduru v databázi AdventureWorks2025, která obsahuje jak INSERT příkaz, tak příkaz.UPDATE Procedura se pak upraví tak, aby spouštěla ekvivalentní operace pomocí jediného MERGE příkazu.

CREATE PROCEDURE dbo.InsertUnitMeasure @UnitMeasureCode NCHAR(3), @Name NVARCHAR(25)
AS
BEGIN
    SET NOCOUNT ON;

    -- Update the row if it exists.
    UPDATE Production.UnitMeasure
    SET Name = @Name
    WHERE UnitMeasureCode = @UnitMeasureCode

    -- Insert the row if the UPDATE statement failed.
    IF (@@ROWCOUNT = 0)
    BEGIN
        INSERT INTO Production.UnitMeasure (
            UnitMeasureCode,
            Name
        )
        VALUES (@UnitMeasureCode, @Name)
    END
END;
GO

-- Test the procedure and return the results.
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Test Value';

SELECT UnitMeasureCode, Name
FROM Production.UnitMeasure
WHERE UnitMeasureCode = 'ABC';
GO

-- Rewrite the procedure to perform the same operations using the
-- MERGE statement.
-- Create a temporary table to hold the updated or inserted values
-- from the OUTPUT clause.
CREATE TABLE #MyTempTable (
    ExistingCode NCHAR(3),
    ExistingName NVARCHAR(50),
    ExistingDate DATETIME,
    ActionTaken NVARCHAR(10),
    NewCode NCHAR(3),
    NewName NVARCHAR(50),
    NewDate DATETIME
);
GO

ALTER PROCEDURE dbo.InsertUnitMeasure @UnitMeasureCode NCHAR(3),
    @Name NVARCHAR(25)
AS
BEGIN
    SET NOCOUNT ON;

    MERGE Production.UnitMeasure AS tgt
    USING (SELECT @UnitMeasureCode, @Name) AS src(UnitMeasureCode, Name)
        ON (tgt.UnitMeasureCode = src.UnitMeasureCode)
    WHEN MATCHED
        THEN
            UPDATE
            SET Name = src.Name
    WHEN NOT MATCHED
        THEN
            INSERT (UnitMeasureCode, Name)
            VALUES (src.UnitMeasureCode, src.Name)
    OUTPUT deleted.*,
        $action,
        inserted.*
    INTO #MyTempTable;
END;
GO

-- Test the procedure and return the results.
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'New Test Value';
EXEC InsertUnitMeasure @UnitMeasureCode = 'XYZ', @Name = 'Test Value';
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Another Test Value';

SELECT * FROM #MyTempTable;

-- Cleanup
DELETE FROM Production.UnitMeasure
WHERE UnitMeasureCode IN ('ABC', 'XYZ');

DROP TABLE #MyTempTable;
GO
CREATE PROCEDURE dbo.InsertUnitMeasure @UnitMeasureCode NCHAR(3),
    @Name NVARCHAR(25)
AS
BEGIN
    SET NOCOUNT ON;

    -- Update the row if it exists.
    UPDATE Production.UnitMeasure
    SET Name = @Name
    WHERE UnitMeasureCode = @UnitMeasureCode

    -- Insert the row if the UPDATE statement failed.
    IF (@@ROWCOUNT = 0)
    BEGIN
        INSERT INTO Production.UnitMeasure (
            UnitMeasureCode,
            Name
        )
        VALUES (@UnitMeasureCode, @Name)
    END
END;
GO

-- Test the procedure and return the results.
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Test Value';

SELECT UnitMeasureCode, Name
FROM Production.UnitMeasure
WHERE UnitMeasureCode = 'ABC';
GO

-- Rewrite the procedure to perform the same operations using the
-- MERGE statement.
ALTER PROCEDURE dbo.InsertUnitMeasure @UnitMeasureCode NCHAR(3),
    @Name NVARCHAR(25)
AS
BEGIN
    SET NOCOUNT ON;

    MERGE Production.UnitMeasure AS tgt
    USING (
        SELECT @UnitMeasureCode,
            @Name
        ) AS src(UnitMeasureCode, Name)
        ON (tgt.UnitMeasureCode = src.UnitMeasureCode)
    WHEN MATCHED
        THEN
            UPDATE SET Name = src.Name
    WHEN NOT MATCHED
        THEN
            INSERT (UnitMeasureCode, Name)
            VALUES (src.UnitMeasureCode, src.Name);
END;
GO

-- Test the procedure and return the results.
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'New Test Value';
EXEC InsertUnitMeasure @UnitMeasureCode = 'XYZ', @Name = 'Test Value';
EXEC InsertUnitMeasure @UnitMeasureCode = 'ABC', @Name = 'Another Test Value';

-- Cleanup
DELETE FROM Production.UnitMeasure
WHERE UnitMeasureCode IN ('ABC', 'XYZ');
GO

B. Použití funkce MERGE k provádění operací UPDATE a DELETE v tabulce v jednom příkazu

Následující příklad se používá MERGE k denní aktualizaci tabulky ProductInventory v databázi AdventureWorks2025 na základě příkazů zpracovávaných v tabulce SalesOrderDetail . Quantity Sloupec ProductInventory tabulky se aktualizuje odečtením počtu objednávek zadaných každý den pro každý produkt v SalesOrderDetail tabulce. Pokud počet objednávek produktu klesne na skladovou úroveň produktu na 0 nebo méně, řádek pro daný produkt se z tabulky odstraní ProductInventory .

CREATE PROCEDURE Production.usp_UpdateInventory @OrderDate DATETIME
AS
MERGE Production.ProductInventory AS tgt
USING (
    SELECT ProductID,
        SUM(OrderQty)
    FROM Sales.SalesOrderDetail AS sod
    INNER JOIN Sales.SalesOrderHeader AS soh
        ON sod.SalesOrderID = soh.SalesOrderID
            AND soh.OrderDate = @OrderDate
    GROUP BY ProductID
    ) AS src(ProductID, OrderQty)
    ON (tgt.ProductID = src.ProductID)
WHEN MATCHED
    AND tgt.Quantity - src.OrderQty <= 0
    THEN
        DELETE
WHEN MATCHED
    THEN
        UPDATE
        SET tgt.Quantity = tgt.Quantity - src.OrderQty,
            tgt.ModifiedDate = GETDATE()
OUTPUT $action,
    Inserted.ProductID,
    Inserted.Quantity,
    Inserted.ModifiedDate,
    Deleted.ProductID,
    Deleted.Quantity,
    Deleted.ModifiedDate;
GO

EXECUTE Production.usp_UpdateInventory '20030501';
CREATE PROCEDURE Production.usp_UpdateInventory @OrderDate DATETIME
AS
MERGE Production.ProductInventory AS tgt
USING (
    SELECT ProductID,
        SUM(OrderQty)
    FROM Sales.SalesOrderDetail AS sod
    INNER JOIN Sales.SalesOrderHeader AS soh
        ON sod.SalesOrderID = soh.SalesOrderID
            AND soh.OrderDate = @OrderDate
    GROUP BY ProductID
    ) AS src(ProductID, OrderQty)
    ON (tgt.ProductID = src.ProductID)
WHEN MATCHED
    AND tgt.Quantity - src.OrderQty <= 0
    THEN
        DELETE
WHEN MATCHED
    THEN
        UPDATE
        SET tgt.Quantity = tgt.Quantity - src.OrderQty,
            tgt.ModifiedDate = GETDATE();
GO

EXECUTE Production.usp_UpdateInventory '20030501';

C. Použití funkce MERGE k provádění operací UPDATE a INSERT v cílové tabulce pomocí odvozené zdrojové tabulky

Následující příklad slouží k MERGE úpravě tabulky SalesReason v databázi AdventureWorks2025 buď aktualizací, nebo vložením řádků.

Pokud hodnota NewName ve zdrojové tabulce odpovídá hodnotě ve Name sloupci cílové tabulky (SalesReason), ReasonType sloupec se aktualizuje v cílové tabulce. Pokud se hodnota NewName neshoduje, vloží se zdrojový řádek do cílové tabulky. Zdrojová tabulka je odvozená tabulka, která používá konstruktor hodnot tabulky Transact-SQL k určení více řádků pro zdrojovou tabulku. Další informace o použití konstruktoru hodnoty tabulky v odvozené tabulce naleznete v tématu Konstruktor hodnoty tabulky (Transact-SQL).

Klauzule OUTPUT může být užitečná k dotazování MERGE na výsledek příkazů, další informace naleznete v tématu VÝSTUPNÍ klauzule (Transact-SQL). Příklad také ukazuje, jak uložit výsledky OUTPUT klauzule do proměnné tabulky. Potom shrnete výsledky MERGE příkazu spuštěním jednoduché operace výběru, která vrátí počet vložených a aktualizovaných řádků.

-- Create a temporary table variable to hold the output actions.
DECLARE @SummaryOfChanges TABLE (Change VARCHAR(20));

MERGE INTO Sales.SalesReason AS tgt
USING (
    VALUES ('Recommendation', 'Other'),
        ('Review', 'Marketing'),
        ('Internet', 'Promotion')
    ) AS src(NewName, NewReasonType)
    ON tgt.Name = src.NewName
WHEN MATCHED
    THEN
        UPDATE
        SET ReasonType = src.NewReasonType
WHEN NOT MATCHED BY TARGET
    THEN
        INSERT (Name, ReasonType)
        VALUES (NewName, NewReasonType)
OUTPUT $action
INTO @SummaryOfChanges;

-- Query the results of the table variable.
SELECT Change,
    COUNT(*) AS CountPerChange
FROM @SummaryOfChanges
GROUP BY Change;

Pokud hodnota NewName ve zdrojové tabulce odpovídá hodnotě ve Name sloupci cílové tabulky (SalesReason), ReasonType sloupec se aktualizuje v cílové tabulce. Pokud se hodnota NewName neshoduje, vloží se zdrojový řádek do cílové tabulky. Zdrojová tabulka je odvozená tabulka, která slouží SELECT ... UNION ALL k určení více řádků pro zdrojovou tabulku.

MERGE INTO Sales.SalesReason AS tgt
USING (
    SELECT 'Recommendation', 'Other'
    UNION ALL
    SELECT 'Review', 'Marketing'
    UNION ALL
    SELECT 'Internet', 'Promotion'
    ) AS src(NewName, NewReasonType)
    ON tgt.Name = src.NewName
WHEN MATCHED
    THEN
        UPDATE SET ReasonType = src.NewReasonType
WHEN NOT MATCHED BY TARGET
    THEN
        INSERT (Name, ReasonType)
        VALUES (NewName, NewReasonType);

D. Vložení výsledků příkazu MERGE do jiné tabulky

Následující příklad zachycuje data vrácená z OUTPUT klauzule MERGE příkazu a vloží tato data do jiné tabulky. Výpis MERGE aktualizuje Quantity sloupec tabulky ProductInventory v databázi AdventureWorks2025 na základě příkazů, které jsou v tabulce SalesOrderDetail zpracovány. Příklad zachycuje aktualizované řádky a vloží je do jiné tabulky, která se používá ke sledování změn inventáře.

CREATE TABLE Production.UpdatedInventory (
    ProductID INT NOT NULL,
    LocationID INT,
    NewQty INT,
    PreviousQty INT,
    CONSTRAINT PK_Inventory PRIMARY KEY CLUSTERED (
        ProductID,
        LocationID
        )
    );
GO

INSERT INTO Production.UpdatedInventory
SELECT ProductID, LocationID, NewQty, PreviousQty
FROM (
    MERGE Production.ProductInventory AS pi
    USING (
        SELECT ProductID, SUM(OrderQty)
        FROM Sales.SalesOrderDetail AS sod
        INNER JOIN Sales.SalesOrderHeader AS soh
            ON sod.SalesOrderID = soh.SalesOrderID
                AND soh.OrderDate BETWEEN '20030701'
                    AND '20030731'
        GROUP BY ProductID
        ) AS src(ProductID, OrderQty)
        ON pi.ProductID = src.ProductID
    WHEN MATCHED
        AND pi.Quantity - src.OrderQty >= 0
        THEN
            UPDATE SET pi.Quantity = pi.Quantity - src.OrderQty
    WHEN MATCHED
        AND pi.Quantity - src.OrderQty <= 0
        THEN
            DELETE
    OUTPUT $action,
        Inserted.ProductID,
        Inserted.LocationID,
        Inserted.Quantity AS NewQty,
        Deleted.Quantity AS PreviousQty
    ) AS Changes(Action, ProductID, LocationID, NewQty, PreviousQty)
WHERE Action = 'UPDATE';
GO

E. Použití funkce MERGE k vložení nebo aktualizaci v cílové hraniční tabulce v grafové databázi

V tomto příkladu vytvoříte tabulky Person uzlů a City hraniční tabulku livesIn. Příkaz použijete MERGE na livesIn okraji a vložíte nový řádek, pokud hrana ještě neexistuje mezi a PersonCity. Pokud už hrana existuje, stačí aktualizovat atribut StreetAddress na hraničním zařízení livesIn .

-- CREATE node and edge tables
CREATE TABLE Person
(
    ID INTEGER PRIMARY KEY,
    PersonName VARCHAR(100)
)
AS NODE
GO

CREATE TABLE City
(
    ID INTEGER PRIMARY KEY,
    CityName VARCHAR(100),
    StateName VARCHAR(100)
)
AS NODE
GO

CREATE TABLE livesIn
(
    StreetAddress VARCHAR(100)
)
AS EDGE
GO

-- INSERT some test data into node and edge tables
INSERT INTO Person VALUES (1, 'Ron'), (2, 'David'), (3, 'Nancy')
GO

INSERT INTO City VALUES (1, 'Redmond', 'Washington'), (2, 'Seattle', 'Washington')
GO

INSERT livesIn SELECT P.$node_id, C.$node_id, c
FROM Person P, City C, (values (1,1, '123 Avenue'), (2,2,'Main Street')) v(a,b,c)
WHERE P.id = a AND C.id = b
GO

-- Use MERGE to update/insert edge data
CREATE OR ALTER PROCEDURE mergeEdge
    @PersonId integer,
    @CityId integer,
    @StreetAddress varchar(100)
AS
BEGIN
    MERGE livesIn
        USING ((SELECT @PersonId, @CityId, @StreetAddress) AS T (PersonId, CityId, StreetAddress)
                JOIN Person ON T.PersonId = Person.ID
                JOIN City ON T.CityId = City.ID)
        ON MATCH (Person-(livesIn)->City)
    WHEN MATCHED THEN
        UPDATE SET StreetAddress = @StreetAddress
    WHEN NOT MATCHED THEN
        INSERT ($from_id, $to_id, StreetAddress)
        VALUES (Person.$node_id, City.$node_id, @StreetAddress) ;
END
GO

-- Following will insert a new edge in the livesIn edge table
EXEC mergeEdge 3, 2, '4444th Avenue'
GO

-- Following will update the StreetAddress on the edge that connects Ron to Redmond
EXEC mergeEdge 1, 1, '321 Avenue'
GO

-- Verify that all the address were added/updated correctly
SELECT PersonName, CityName, StreetAddress
FROM Person , City , livesIn
WHERE MATCH(Person-(livesIn)->city)
GO