Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Platí na:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics (dedicated SQL pool only)
SQL databáze v Microsoft Fabric
Sklad 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.
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í
MERGEk 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 ANSIUPDATE FROM ... JOINjako alternativní řešení, dokud nebude verze 10.0.17829.0. - Aktualizace
MERGEse implementuje jako dvojice odstranění a vložení. Ovlivněný počet řádků aktualizaceMERGEzahrnuje odstraněné a vložené řádky. -
MERGE...WHEN NOT MATCHED INSERTnepodporuje tabulky seIDENTITYsloupci. - Konstruktor hodnot tabulky nelze použít v
USINGklauzuli zdrojové tabulky. SloužíSELECT ... UNION ALLk 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 SETneboINSERTuvnitřMERGE(nikoli specifické pro žádnouWHEN [NOT] MATCHEDklauzuli) - Libovolný sloupec v
JOINpodmínce má neclusterovaný index (NCI). - Cílová tabulka je
HASHdistribuovaná
Pokud se tato chyba najde, navrhovaná alternativní řešení jsou následující:
- Odeberte neclusterovaný index (NCI) ze
JOINsloupců nebo spojujte sloupce bez NCI. Pokud později aktualizujete podkladové tabulky tak, aby zahrnovaly NCI doJOINsloupců, může být vášMERGEpří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,
MERGEa 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
MERGEpří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éhoDELETEINSERTa , místoUPDATEneboMERGE.
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, aDELETElogika může fungovat lépe, s méně blokujícími, než jeMERGEpří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čí, žeHOLDLOCKse zabrání porušení jedinečných klíčů.HOLDLOCKje synonymem proSERIALIZABLEúroveň izolace transakcí, která neumožňuje jiným souběžným transakcím upravovat data, která tato transakce přečetla.SERIALIZABLEje 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 nalezneteHOLDLOCKv 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é
WHENklauzuli. NapříkladWHEN 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í vONklauzuli 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 vWHENklauzulíchMERGEpříkazu. Příkaz můžete například začlenitMERGEdo 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
TEMPLATEa v průvodci plánem zadejte nápověduPARAMETERIZATION FORCEDdotazu. Další informace naleznete v tématu Určení chování parametrizace dotazu pomocí průvodců plánem. - Pokud
MERGEjsou příkazy spouštěny často v databázi, zvažte nastaveníPARAMETERIZATIONmožnosti databáze naFORCED. Při nastavování této možnosti buďte opatrní. TatoPARAMETERIZATIONmož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
MERGEprovede ú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ů:
-
ONPomocí 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 MATCHEDklauzuli určete, jestli cílový řádek již byl aktualizován předchozí dávkou. - Pomocí další podmínky v
WHEN MATCHEDklauzuli aSETlogice 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.ORDERUNIQUEPomocí a tipů vOPENROWSET(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
ORDERoptimalizá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í.
- Pomocí čítače stmt sloučení v zobrazení dynamické správy sys.dm_exec_query_optimizer_info vrátíte počet optimalizací dotazů, které jsou pro
MERGEpříkazy. -
merge_action_typePomocí atributu v zobrazení sys.dm_exec_plan_attributes dynamické správy vrátíte typ plánu spuštění triggeru, který se použije jako výsledekMERGEpříkazu. - Relace rozšířených událostí slouží ke shromažďování dat pro
MERGEpříkaz stejným způsobem jako u jiných příkazů jazyka DML (Data Manipulat Language). Další informace o přehledu rozšířených událostí najdete v tématu Rychlý start : Rozšířené události a Použití SSMS XEvent Profiler.
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