Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Vonatkozik a következőkre:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics (dedicated SQL pool only)
SQL adatbázis a Microsoft Fabric-ben
Raktár a Microsoft Fabric-ben
Az MERGE utasítás beszúrási, frissítési vagy törlési műveleteket futtat egy céltáblán egy forrástáblával való illesztés eredményeiből. Szinkronizálhat például két táblát úgy, hogy sorokat szúr be, frissít vagy töröl az egyik táblában a másik táblában található különbségek alapján.
Ez a cikk különböző szintaxisokat, argumentumokat, megjegyzéseket, engedélyeket és példákat tartalmaz a kiválasztott termékverzió alapján. Válassza ki a kívánt termékverziót a verzió legördülő listájából.
Note
A Fabric Data Warehouse MERGE előzetes verzióban érhető el.
Transact-SQL szintaxis konvenciók
Syntax
Az SQL Server és az Azure SQL Database szintaxisa:
[ 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>
Az Azure Synapse Analytics, Fabric Data Warehouse szintaxisa:
[ 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
A COMMON_TABLE_EXPRESSION <>
Az utasítás hatókörében MERGE definiált ideiglenes elnevezett eredményhalmazt vagy nézetet (más néven közös táblakifejezést) adja meg. Az eredményhalmaz egy egyszerű lekérdezésből származik, és az MERGE utasítás hivatkozik gombra. További információ: WITH common_table_expression (Transact-SQL).
TOP ( kifejezés ) [ PERCENT ]
Az érintett sorok számát vagy százalékos arányát adja meg.
kifejezés lehet szám vagy a sorok százalékos aránya. A kifejezésben TOP hivatkozott sorok nincsenek rendezve semmilyen sorrendben. További információ: TOP (Transact-SQL).
A TOP záradék a teljes forrástábla és a céltábla teljes illesztése, valamint a beszúrási, frissítési vagy törlési művelethez nem megfelelő illesztett sorok eltávolítása után érvényes. A TOP záradék tovább csökkenti az összekapcsolt sorok számát a megadott értékre. Ezek a műveletek (beszúrás, frissítés vagy törlés) rendezetlen módon vonatkoznak a többi illesztett sorra. Vagyis nincs olyan sorrend, amelyben a sorok el vannak osztva a WHEN záradékokban meghatározott műveletek között. A (10) megadása TOP például 10 sort érint. Ezen sorok közül 7 frissíthető és 3 beszúrható, illetve 1 törölhető, 5 frissítve és 4 beszúrva stb.
A forrástábla szűrői nélkül az MERGE utasítás táblavizsgálatot vagy fürtözött indexvizsgálatot végezhet a forrástáblán, valamint a céltábla táblavizsgálatát vagy fürtözött indexvizsgálatát. Ezért az I/O teljesítménye néha akkor is hatással van, ha a TOP záradékkal több köteg létrehozásával módosít egy nagy táblát. Ebben a forgatókönyvben fontos biztosítani, hogy minden egymást követő köteg új sorokat célozhasson meg.
database_name
Annak az adatbázisnak a neve, amelyben a target_table található.
schema_name
Annak a sémának a neve, amelyhez target_table tartozik.
target_table
Az a tábla vagy nézet, amely alapján <table_source> az adatsorok egyeznek <clause_search_condition>.
target_table az utasítás záradékai által WHEN megadott beszúrási, frissítési vagy törlési MERGE műveletek célja.
Ha target_table nézet, az ellene irányuló műveleteknek meg kell felelniük a nézetek frissítésének feltételeinek. További információ: Adatok módosítása nézeten keresztül.
target_table nem lehet távoli tábla. target_table nem definiálhatók rajta szabályok. target_table nem lehet memóriaoptimalizált tábla.
A tippek megadhatóak <merge_hint>.
<merge_hint> az Azure Synapse Analytics nem támogatja.
[ MINT ] table_alias
Egy másik név, amely a target_table táblára hivatkozik.
TABLE_SOURCE HASZNÁLATA <>
A target_table adatsoraival egyező adatforrást adja meg az alapján <merge_search_condition>. Ennek az egyezésnek az eredménye diktálja az utasítás záradékai WHEN által MERGE végrehajtandó műveleteket.
<table_source> Lehet távoli tábla vagy távoli táblákhoz hozzáférő származtatott tábla.
<table_source> olyan származtatott tábla lehet, amely a Transact-SQL táblaérték-konstruktort használja egy tábla több sor megadásával történő létrehozásához.
<table_source> egy olyan származtatott tábla lehet, amely SELECT ... UNION ALL több sor megadásával hoz létre egy táblát.
[ MINT ] table_alias
Egy másik név, amely a table_source táblára hivatkozik.
A záradék szintaxisával és argumentumával kapcsolatos további információkért lásd: FROM (Transact-SQL).
A merge_search_condition <>
Meghatározza azokat a feltételeket, amelyeken <table_source>a target_table összekapcsolja az illesztéseket annak meghatározásához, hogy hol egyeznek.
Caution
Fontos, hogy csak a céltáblából származó oszlopokat adja meg egyezés céljából. Vagyis adja meg a céltábla azon oszlopait, amelyek a forrástábla megfelelő oszlopával vannak összehasonlítva. Ne próbáljon javítani a lekérdezési teljesítményen a záradék céltáblájának ON sorainak szűrésével, például a megadásával AND NOT target_table.column_x = value. Ez váratlan és helytelen eredményeket adhat vissza.
HA MEGFELEL, AKKOR <merge_matched>
Megadja, hogy a *target_table összes olyan sora, amely megfelel a visszaadott <table_source> ON <merge_search_condition>soroknak, és megfelel a további keresési feltételeknek, a záradéknak megfelelően <merge_matched> frissüljön vagy törölve legyen.
Az MERGE utasítás legfeljebb két WHEN MATCHED záradékkal rendelkezhet. Ha két záradék van megadva, az első záradékot záradékkal kell kiegészíteni AND<search_condition> . Egy adott sor esetében a második WHEN MATCHED záradék csak akkor lesz alkalmazva, ha az első nem. Ha két WHEN MATCHED záradék van, az egyiknek meg kell adnia egy UPDATE műveletet, a másiknak pedig egy DELETE műveletet. Ha UPDATE a <merge_matched> záradék meg van adva, és egynél több sor <table_source> felel meg egy sornak target_table alapján <merge_search_condition>, az SQL Server hibát ad vissza. Az MERGE utasítás nem tudja többször frissíteni ugyanazt a sort, vagy frissíteni és törölni ugyanazt a sort.
HA NEM EGYEZIK [CÉL] AKKOR <merge_not_matched>
Megadja, hogy a rendszer minden olyan sorhoz beszúrjon egy sort target_table, amely <table_source> ON <merge_search_condition> nem egyezik meg a target_table egy sorával, de ha van ilyen, egy további keresési feltételnek is megfelel. A beszúrni kívánt értékeket a <merge_not_matched> záradék határozza meg. Az MERGE utasításnak csak egy WHEN NOT MATCHED [ BY TARGET ] záradéka lehet.
HA NEM EGYEZIK A FORRÁS, AKKOR <MERGE_MATCHED>
Megadja, hogy a *target_table összes olyan sora, amely nem egyezik a visszaadott <table_source> ON <merge_search_condition>sorokkal, és amelyek megfelelnek a további keresési feltételeknek, a záradéknak megfelelően <merge_matched> frissülnek vagy törlődnek.
Az MERGE utasítás legfeljebb két WHEN NOT MATCHED BY SOURCE záradékkal rendelkezhet. Ha két záradék van megadva, akkor az első záradékhoz záradékot AND<clause_search_condition> kell mellékelni. Egy adott sor esetében a második WHEN NOT MATCHED BY SOURCE záradék csak akkor lesz alkalmazva, ha az első nem. Ha két WHEN NOT MATCHED BY SOURCE záradék van, akkor meg kell adnia egy UPDATE műveletet, egy pedig meg kell adnia egy DELETE műveletet. Csak a céltáblából származó oszlopokra lehet hivatkozni a következőben <clause_search_condition>: .
Ha a rendszer nem ad vissza <table_source>sorokat, a forrástábla oszlopai nem érhetők el. Ha a záradékban megadott frissítési vagy törlési <merge_matched> művelet a forrástáblában lévő oszlopokra hivatkozik, a rendszer a 207-s hibát (érvénytelen oszlopnevet) adja vissza. A záradék WHEN NOT MATCHED BY SOURCE THEN UPDATE SET TargetTable.Col1 = SourceTable.Col1 például az utasítás meghiúsulását okozhatja, mert Col1 a forrástáblában nem érhető el.
ÉS <clause_search_condition>
Érvényes keresési feltételt ad meg. További információ: Keresési feltétel (Transact-SQL).
<table_hint_limited>
Egy vagy több táblázatra vonatkozó tippet ad meg a céltáblára az utasítás által végrehajtott beszúrási, frissítési vagy törlési MERGE műveletek mindegyikéhez. A WITH kulcsszó és a zárójelek megadása kötelező.
NOLOCK és READUNCOMMITTED nem engedélyezettek. A táblázatos tippekről további információt a Table hints (Transact-SQL) című témakörben talál.
TABLOCK Az utasítás céljának INSERT megfelelő táblára vonatkozó tipp megadása ugyanolyan hatással van, mint a TABLOCKX tipp megadására. Az asztalra kizárólagos zárolás kerül. Ha a FORCESEEK meg van adva, az a forrástáblához csatlakoztatott céltábla implicit példányára vonatkozik.
Caution
A megadásával READPASTWHEN NOT MATCHED [ BY TARGET ] THEN INSERT olyan műveletek következhetnek beINSERT, amelyek megsértik UNIQUE a korlátozásokat.
INDEX ( index_val [ ,... n ] )
Megadja a céltábla egy vagy több indexének nevét vagy azonosítóját, amely implicit illesztéseket végez a forrástáblával. További információkért lásd: Tábla-javallatok (Transact-SQL).
<output_clause>
Egy sort ad vissza a target_table minden olyan sorához, amely adott sorrendben frissül, beszúrt vagy törölve van.
$action a kimeneti záradékban adható meg.
$action egy nvarchar(10) típusú oszlop, amely minden sor három értékének egyikét adja vissza: INSERT, UPDATEvagy DELETE, az adott sorban végrehajtott műveletnek megfelelően. A OUTPUT záradék az ajánlott módszer egy adott sor által érintett sorok lekérdezésére vagy megszámlálására MERGE. A záradék argumentumairól és viselkedéséről további információt az OUTPUT záradékban (Transact-SQL) talál.
OPTION ( <query_hint> [ ,... n ] )
Meghatározza, hogy az optimalizáló tippek segítségével szabja testre az adatbázismotor az utasítást. További információ: Lekérdezési tippek (Transact-SQL).
<merge_matched>
Megadja az összes olyan target_table sorra alkalmazott frissítési vagy törlési műveletet, amely nem egyezik a visszaadott <table_source> ON <merge_search_condition>sorokkal, és amelyek megfelelnek a további keresési feltételeknek.
FRISSÍTÉS set_clause <>
Megadja a céltáblában frissíteni kívánt oszlop- vagy változónevek listáját, valamint azokat az értékeket, amelyekkel frissíteni szeretné őket.
A záradék argumentumairól további információt az UPDATE (Transact-SQL) című témakörben talál. Ha egy változót egy oszlop értékére állít be, az nem támogatott.
DELETE
Megadja, hogy a target_table sorainak megfelelő sorok törlődnek.
<merge_not_matched>
Megadja a céltáblába beszúrni kívánt értékeket.
( column_list )
A céltábla egy vagy több oszlopának listája, amelyben adatokat szeretne beszúrni. Az oszlopokat egyrészes névként kell megadni, különben az MERGE utasítás meghiúsul.
column_list zárójelek közé kell tenni, és vesszővel kell elválasztani.
ÉRTÉKEK ( values_list )
Olyan állandók, változók vagy kifejezések vesszővel tagolt listája, amelyek értékeket adnak vissza a céltáblába való beszúráshoz. A kifejezések nem tartalmazhatnak utasítást EXECUTE .
ALAPÉRTELMEZETT ÉRTÉKEK
Kényszeríti a beszúrt sort, hogy tartalmazza az egyes oszlopokhoz definiált alapértelmezett értékeket.
A záradékról további információt az INSERT (Transact-SQL) című témakörben talál.
<search_condition>
Megadja a megadható <merge_search_condition> keresési feltételeket vagy <clause_search_condition>a . A záradék argumentumairól további információt a Keresési feltétel (Transact-SQL) című témakörben talál.
<gráfkeresési minta>
A gráfegyezés mintáját adja meg. A záradék argumentumairól további információt a HOL.VAN (Transact-SQL) című témakörben talál.
Remarks
Az utasításhoz MERGE leírt feltételes viselkedés akkor működik a legjobban, ha a két tábla egyező jellemzők összetett keverékével rendelkezik. Például beszúrhat egy sort, ha az nem létezik, vagy frissíthet egy sort, ha megegyezik. Ha egyszerűen frissít egy táblát egy másik tábla sorai alapján, javítsa a teljesítményt és a méretezhetőséget a , INSERTés UPDATE utasításokkalDELETE. Például:
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);
A három MATCHED záradék közül legalább egyet meg kell adni, de bármilyen sorrendben megadhatók. Egy változó nem frissíthető többször ugyanabban MATCHED a záradékban.
A céltáblán az utasítás által MERGE megadott beszúrási, frissítési vagy törlési műveletet a rajta meghatározott korlátozások korlátozzák, beleértve az esetleges kaszkádolt hivatkozási integritási korlátozásokat is. Ha IGNORE_DUP_KEY a céltábla bármely egyedi indexéhez tartozik ON , MERGE figyelmen kívül hagyja ezt a beállítást.
Az MERGE utasításhoz pontosvesszőre (;) van szükség utasítás-kifejezésként. Az 10713-ás hiba akkor jelenik meg, ha egy MERGE utasítás a kifejezés nélkül fut.
A MERGE után használva a beszúrt, frissített és törölt sorok teljes számát adja vissza az ügyfélnek.
MERGE teljes mértékben fenntartott kulcsszó, ha az adatbázis kompatibilitási 100 szintje értéke vagy magasabb. Az MERGE utasítás elérhető mind az 90100 adatbázis-kompatibilitási szinteken, mind pedig az adatbázis-kompatibilitási szinteken. A kulcsszó azonban nem foglalható le teljesen, ha az adatbázis kompatibilitási szintje a következőre 90van állítva.
Caution
Ne használja az utasítást az MERGEüzenetsoros frissítési replikáció használatakor. A MERGE várólistán lévő frissítési eseményindító nem kompatibilis. Cserélje le az MERGE utasítást egy és INSERT egy UPDATE utasításra.
Az Azure Synapse Analytics szempontjai
Az Azure Synapse Analyticsben a parancs az SQL Serverhez és az MERGE Azure SQL Database-hez képest a következő különbségeket követi.
- A
MERGEterjesztésikulcs-oszlop frissítése nem támogatott a 10.0.17829.0-nál régebbi buildekben. Ha nem tudja szüneteltetni vagy kényszeríteni a frissítést, használja az ANSI-utasítástUPDATE FROM ... JOINkerülő megoldásként a 10.0.17829.0-s verzióig. - A
MERGEfrissítés törlési és beszúrási párként van implementálva. A frissítés érintett sorszámaMERGEtartalmazza a törölt és a beszúrt sorokat. -
MERGE...WHEN NOT MATCHED INSERToszlopokkal rendelkezőIDENTITYtáblák esetében nem támogatott. - A táblaérték-konstruktor nem használható a
USINGforrástábla záradékában. TöbbSELECT ... UNION ALLsorból származó forrástáblát hozhat létre. - A különböző disztribúciós típusú táblák támogatását ebben a táblázatban ismertetjük:
| MERGE CLAUSE az Azure Synapse Analyticsben | Támogatott TARGET terjesztési tábla |
Támogatott FORRÁS terjesztési tábla | Comment |
|---|---|---|---|
WHEN MATCHED |
Minden terjesztési típus | Minden terjesztési típus | |
NOT MATCHED BY TARGET |
HASH |
Minden terjesztési típus | Két tábla szinkronizálására használható UPDATE/DELETE FROM...JOIN . |
NOT MATCHED BY SOURCE |
Minden terjesztési típus | Minden terjesztési típus |
Tip
Ha a terjesztési kivonatkulcsot használja oszlopkéntJOIN, MERGE és csak egyenlőségi összehasonlítást végez, kihagyhatja a terjesztési kulcsot a WHEN MATCHED THEN UPDATE SET záradék oszlopainak listájából, mivel ez redundáns frissítés.
Az Azure Synapse Analyticsben a MERGE 10.0.17829.0-nál régebbi buildek parancsa bizonyos feltételek mellett inkonzisztens állapotban hagyhatja a céltáblát, és a sorok helytelen eloszlásba kerülnek, ami miatt a későbbi lekérdezések bizonyos esetekben helytelen eredményeket adnak vissza. Ez a probléma két esetben fordulhat elő:
| Scenario | Comment |
|---|---|
|
1. eset Másodlagos indexeket vagy kényszereket MERGE tartalmazó elosztott KIVONAT-táblán TARGET való használatUNIQUE. |
- A Synapse SQL 10.0.15563.0-s és újabb verzióiban javítva. – Ha SELECT @@VERSION a 10.0.15563.0-s verziónál alacsonyabb verziót ad vissza, a javítás elvégzéséhez manuálisan szüneteltetje és folytassa a Synapse SQL-készletet.- Amíg a javítást nem alkalmazza a Synapse SQL-készletre, ne használja a MERGE parancsot másodlagos indexekkel vagy HASH korlátozásokkal rendelkező elosztott TARGET táblákonUNIQUE. |
|
2. eset A MERGE használatával frissítheti a HASH elosztott tábla terjesztésikulcs-oszlopát. |
- Kijavítva a Synapse SQL 10.0.17829.0-s és újabb verzióiban. – Ha SELECT @@VERSION a 10.0.17829.0-s verziónál alacsonyabb verziót ad vissza, a javítás elvégzéséhez manuálisan szüneteltetje és folytassa a Synapse SQL-készletet.– Amíg a javítást nem alkalmazza a Synapse SQL-készletre, ne használja a parancsot a MERGE terjesztési kulcs oszlopainak frissítéséhez. |
A két forgatókönyv frissítései nem javítják ki az előző MERGE végrehajtás által már érintett táblákat. Az alábbi szkriptekkel manuálisan azonosíthatja és kijavíthatja az érintett táblákat.
Ha ellenőrizni szeretné, hogy egy adatbázisban mely HASH elosztott táblák lehetnek aggályosak (ha a korábban említett esetekben használják), futtassa ezt az utasítást:
-- 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';
Ha ellenőrizni szeretné, hogy az HASH elosztott táblákra MERGE hatással van-e az 1. vagy a 2. eset, kövesse az alábbi lépéseket annak ellenőrzéséhez, hogy a táblák sorai helytelen eloszlásban vannak-e. Ha no need for repair a visszaadott érték nem érinti ezt a táblát.
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
Az érintett táblák javításához futtassa ezeket az utasításokat az összes sor másolásához a régi táblából egy új táblába.
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
Bizonyos esetekben egy utasítás akkor is hibát MERGEokozhat, CREATE TABLE failed because column <> in table <> exceeds the maximum of 1024 columns. ha a cél- vagy forrástábla nem tartalmaz 1024 oszlopot. Ez a forgatókönyv akkor fordulhat elő, ha a következő feltételek bármelyike teljesül:
- Több oszlop van megadva egy
DELETE,UPDATE SETvagyINSERTműveletben belülMERGE(nem egy záradékraWHEN [NOT] MATCHEDjellemző) - A feltétel bármely oszlopa
JOINrendelkezik nemclustered indexkel (NCI) - A céltábla el van
HASHosztva
Ha ez a hiba található, a javasolt kerülő megoldások a következők:
- Távolítsa el a nemclustered indexet (NCI) az
JOINoszlopokból, vagy csatlakozzon az NCI nélküli oszlopokhoz. Ha később úgy frissíti az alapul szolgáló táblákat, hogy egy NCI-t tartalmazzon azJOINoszlopokon, akkor azMERGEutasítás futásidőben valószínűleg érzékeny erre a hibára. További információ: DROP INDEX. - Az UPDATE, a DELETE és az INSERT utasítást használja ahelyett, hogy a következőt használjuk
MERGE: .
Trigger implementálása
Az utasításban megadott minden beszúrási, frissítési vagy törlési művelet esetében az MERGE SQL Server elindítja a céltáblán definiált megfelelő AFTER eseményindítókat, de nem garantálja, hogy melyik művelet aktiválja először vagy utoljára az eseményindítókat. Az ugyanahhoz a művelethez definiált triggerek betartják a megadott sorrendet. Az eseményindítók kilövési sorrendjének beállításáról további információt az Első és az Utolsó eseményindító megadása című témakörben talál.
Ha a céltábla rendelkezik egy utasítással INSTEAD végzett beszúrási, frissítési vagy törlési művelethez definiált MERGE OF eseményindítóval, akkor az utasításban megadott összes művelethez engedélyezni INSTEAD kell az MERGE OF eseményindítót.
Ha bármelyik INSTEAD OF UPDATE vagy INSTEAD OF DELETE eseményindítót definiálja target_table, a frissítési vagy törlési műveletek nem futnak. Ehelyett az eseményindítók kigyulladnak, a beszúrt és törölt táblák pedig ennek megfelelően lesznek feltöltve.
Ha bármelyik INSTEAD OF-eseményindító INSERT definiálva van target_table, a beszúrási művelet nem lesz végrehajtva. Ehelyett a tábla ennek megfelelően töltődik fel.
Note
A különálló INSERT, UPDATEés DELETE az utasításoktól eltérően az eseményindítón belül tükröződő @@ROWCOUNT sorok száma magasabb lehet. Az @@ROWCOUNT eseményindítók AFTER belső része (az adatmódosítási utasításoktól függetlenül, amelyeket az eseményindító rögzít) az érintett MERGEsorok teljes számát tükrözi. Ha például egy MERGE utasítás beszúr egy sort, frissít egy sort, és töröl egy sort, @@ROWCOUNT akkor az eseményindító AFTER három lesz, még akkor is, ha az eseményindító csak utasításokhoz INSERT van deklarálva.
Permissions
Engedélyre van szükség SELECT a forrástáblában és INSERTa UPDATEcéltáblán, vagy DELETE engedélyeket igényel. További információ: SELECT (Transact-SQL), INSERT (Transact-SQL), UPDATE (Transact-SQL), és DELETE (Transact-SQL) cikkekben.
Ajánlott indexelési eljárások
Az utasítás használatával MERGE az egyes DML-utasításokat egyetlen utasításra cserélheti. Ez javíthatja a lekérdezési teljesítményt, mivel a műveletek egyetlen utasításban vannak végrehajtva, így minimalizálva a forrás- és céltáblákban lévő adatok feldolgozásának hányszorosát. A teljesítménynövekedés azonban attól függ, hogy megfelelő indexek, illesztések és egyéb szempontok vannak-e érvényben.
Az utasítás teljesítményének MERGE javítása érdekében az alábbi indexelési irányelveket javasoljuk:
- Indexek létrehozása a forrás és a cél közötti illesztés megkönnyítéséhez
MERGE:- Hozzon létre egy indexet a forrástábla illesztésoszlopaihoz, amely a céltáblához tartozó illesztéslogikát lefedő kulcsokkal rendelkezik. Ennek lehetőség szerint egyedinek kell lennie.
- Emellett hozzon létre egy indexet a céltábla illesztőoszlopaihoz. Ennek lehetőleg egyedi fürtözött indexnek kell lennie.
- Ez a két index biztosítja, hogy a táblák adatai rendezve legyenek, az egyediség pedig segíti az összehasonlítás teljesítményét. A lekérdezés teljesítménye javul, mert a lekérdezésoptimalizálónak nem kell további ellenőrzési feldolgozást végeznie az ismétlődő sorok megkereséséhez és frissítéséhez, és nincs szükség további rendezési műveletekre.
- Kerülje azokat a táblákat, amelyek bármilyen típusú oszlopcentrikus indexet tartalmaznak az utasítások céljaként
MERGE. Az UPDAT-ekhez hasonlóan az oszlopcentrikus indexekkel is jobb teljesítményt érhet el egy szakaszos sortártábla frissítésével, majd egy kötegeltDELETEésINSERTegyUPDATEvagyMERGE.
A MERGE egyidejűségi szempontjai
A zárolás szempontjából különbözik a különálló, MERGE egymást követő INSERTés UPDATEDELETE utasításoktól.
MERGE továbbra is végrehajtja INSERT, UPDATEés DELETE műveleteket, azonban különböző zárolási mechanizmusok használatával. Hatékonyabb lehet különálló , INSERTés UPDATE utasításokat írni DELETEbizonyos alkalmazásigényekhez. Nagy léptékben összetett egyidejűségi problémákat eredményezhet, MERGE vagy speciális hibaelhárítást igényelhet. Ezért tervezze meg, hogy alaposan tesztelje az összes MERGE utasítást, mielőtt üzembe helyeznénk az éles környezetben.
MERGE az utasítások az alábbi forgatókönyvekben (de nem kizárólag) a különálló INSERT, UPDATEés DELETE a műveletek megfelelő helyettesítői:
- A nagy sorszámú ETL-műveletek végrehajtása olyan időszakban történik, amikor más egyidejű műveletek nem* várhatók. Ha nagy egyidejűség várható, a különálló
INSERT,UPDATEésDELETEa logika jobban teljesíthet, kevesebb blokkolással, mint egyMERGEutasítás. - A kis sorszámokat és tranzakciókat tartalmazó összetett műveletek hosszabb ideig nem hajthatóak végre.
- Összetett műveletek felhasználói táblákkal, amelyekben az indexek az optimális végrehajtási tervek biztosítása érdekében tervezhetők, elkerülve a táblavizsgálatokat és a kereséseket az indexvizsgálatok vagy - ideális esetben - az indexkeresések javára.
Az egyidejűség egyéb szempontjai:
- Bizonyos esetekben, amikor az egyedi kulcsokat várhatóan a program beszúrja és frissíti
MERGE, megadja azHOLDLOCKegyedi kulcsok megsértésének megelőzését.HOLDLOCKa tranzakcióelkülönítési szint szinonimájaSERIALIZABLE, amely nem teszi lehetővé, hogy más egyidejű tranzakciók módosítsák a tranzakció által beolvasott adatokat.SERIALIZABLEa legbiztonságosabb elkülönítési szint, de a legkevésbé egyidejűséget biztosítja más tranzakciókkal, amelyek megőrzik az adattartományokra vonatkozó zárolásokat, hogy megakadályozzák a fantomsorok beszúrását vagy frissítését olvasás közben. További információ:HOLDLOCKTable Hints and SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
JOIN – ajánlott eljárások
Az utasítás teljesítményének javítása és a MERGE megfelelő eredmények elérése érdekében javasoljuk a következő illesztési irányelveket:
- Csak olyan keresési feltételeket adjon meg a
ON <merge_search_condition>záradékban, amelyek meghatározzák a forrás- és céltáblákban szereplő adatok egyeztetésének feltételeit. Vagyis csak olyan oszlopokat adjon meg a céltáblából, amelyek a forrástábla megfelelő oszlopaihoz vannak összehasonlítani. - Ne tartalmazzon más értékekkel, például állandókkal való összehasonlítást.
A forrás- vagy céltáblák sorainak szűréséhez használja az alábbi módszerek egyikét.
- Adja meg a sorszűrés keresési feltételét a megfelelő
WHENzáradékban. Például:WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT.... - Definiáljon egy nézetet a forráson vagy a célon, amely visszaadja a szűrt sorokat, és hivatkozzon a nézetre forrásként vagy céltáblaként. Ha a nézet a céltáblán van definiálva, az ellene irányuló műveleteknek meg kell felelniük a nézetek frissítésének feltételeinek. Az adatok nézeten keresztüli frissítéséről további információt az Adatok módosítása nézeten keresztül című témakörben talál.
- A záradék használatával kiszűrheti a
WITH <common table expression>sorokat a forrás- vagy céltáblákból. Ez a módszer hasonló a záradékban szereplőONtovábbi keresési feltételek megadásához, és helytelen eredményeket eredményezhet. Javasoljuk, hogy a implementálás előtt ne használja ezt a módszert, vagy tesztelje alaposan.
Az utasítás illesztési MERGE művelete ugyanúgy van optimalizálva, mint egy utasítás illesztése SELECT . Vagyis amikor az SQL Server feldolgozza az illesztéseket, a lekérdezésoptimalizáló kiválasztja az illesztés feldolgozásának leghatékonyabb módszerét (több lehetőség közül). Ha a forrás és a cél hasonló méretű, és a korábban ismertetett index-irányelveket alkalmazza a forrás- és céltáblákra, az egyesítési operátor a leghatékonyabb lekérdezési terv. Ennek az az oka, hogy mindkét táblát egyszer ellenőrzi a rendszer, és nincs szükség az adatok rendezésére. Ha a forrás kisebb, mint a céltábla, a beágyazott hurkok operátora előnyösebb.
Egy adott illesztés használatát kényszerítheti az utasítás záradékának OPTION (<query_hint>) megadásávalMERGE. Javasoljuk, hogy ne használja a kivonat illesztése lekérdezési tippként az utasításokhoz MERGE , mert ez az illesztéstípus nem használ indexeket.
A paraméterezés ajánlott eljárásai
Ha egy SELECT, INSERT, , UPDATEvagy DELETE utasítás paraméterek nélkül fut, az SQL Server lekérdezésoptimalizálója dönthet úgy, hogy belsőleg paraméterezi az utasítást. Ez azt jelenti, hogy a lekérdezésben található literális értékek paraméterekkel lesznek helyettesítve. Az utasítás INSERT dbo.MyTable (Col1, Col2) VALUES (1, 10)például belsőleg INSERT dbo.MyTable (Col1, Col2) VALUES (@p1, @p2)is implementálható. Ez az egyszerű paraméterezésnek nevezett folyamat növeli a relációs motor azon képességét, hogy egyezzen az új SQL-utasításokkal a meglévő, korábban lefordított végrehajtási tervekkel. A lekérdezési teljesítmény javulhat, mert a lekérdezés-fordítások és újrafordítások gyakorisága csökken. A lekérdezésoptimalizáló nem alkalmazza az egyszerű paraméterezési folyamatot az utasításokra MERGE . Ezért előfordulhat, MERGE hogy a konstans értékeket tartalmazó utasítások nem hajtanak végre, és nem egyesítenek INSERT, UPDATEvagy DELETE utasításokat, mert minden egyes utasítás végrehajtásakor egy új tervet állít össze a MERGE rendszer.
A lekérdezési teljesítmény javítása érdekében a következő paraméterezési irányelveket javasoljuk:
- A záradékban és az
ON <merge_search_condition>WHENutasítás záradékaiban szereplő összes literális érték paraméterezéseMERGE. Az utasítást például belefoglalhatjaMERGEegy tárolt eljárásba, amely a literális értékeket a megfelelő bemeneti paraméterekkel helyettesíti. - Ha nem tudja paraméterezni az utasítást, hozzon létre egy típusterv-útmutatót
TEMPLATE, és adja meg aPARAMETERIZATION FORCEDlekérdezési tippet a terv útmutatójában. További információ: Lekérdezésparaméterezési viselkedés megadása terv-útmutatók használatával. - Ha
MERGEaz utasítások végrehajtása gyakran történik az adatbázisban, fontolja meg azPARAMETERIZATIONadatbázisFORCEDbeállítását. A beállításnál körültekintően kell eljárni. APARAMETERIZATIONbeállítás egy adatbázisszintű beállítás, amely az adatbázison belüli összes lekérdezés feldolgozását befolyásolja. További információ: Kényszerített paraméterezés. - Az útmutatók tervezésének újabb és egyszerűbb alternatívaként érdemes lehet hasonló stratégiát használni a Lekérdezéstár tippjeivel. További információ: Query Store-tippek.
TOP záradék – ajánlott eljárások
Az utasításban a MERGETOP záradék a forrástábla és a céltábla összekapcsolása után érintett sorok számát vagy százalékos arányát határozza meg, majd a beszúrási, frissítési vagy törlési műveletre nem jogosult sorok eltávolítása után. A TOP záradék tovább csökkenti az illesztett sorok számát a megadott értékre, a beszúrási, frissítési vagy törlési műveleteket pedig rendezetlen módon alkalmazza a rendszer a többi illesztett sorra. Vagyis nincs olyan sorrend, amelyben a sorok el vannak osztva a WHEN záradékokban meghatározott műveletek között. A beállítás TOP (10) például 10 sort érint; ezek közül 7 frissíthető és 3 beszúrható, illetve 1 törölhető, 5 frissítve és 4 beszúrva stb.
Gyakran használják a TOP záradékot adatmanipulációs nyelv (DML) műveletek végrehajtására egy nagy táblán kötegekben. Ha a TOP záradékot erre a célra használja az MERGE utasításban, fontos tisztában lenni a következő következményekkel.
Az I/O-teljesítményt befolyásolhatja.
Az
MERGEutasítás a forrás- és a céltáblák teljes táblázatvizsgálatát végzi. A művelet kötegekre való felosztása csökkenti a kötegenként végrehajtott írási műveletek számát; azonban minden köteg teljes táblázatvizsgálatot végez a forrás- és céltáblákon. Az eredményül kapott olvasási tevékenység befolyásolhatja a lekérdezés teljesítményét és a táblákon végzett egyéb egyidejű tevékenységeket.Helytelen eredmények fordulhatnak elő.
Fontos gondoskodni arról, hogy minden egymást követő köteg új sorokat célozhasson meg, vagy nem kívánt viselkedés, például ismétlődő sorok helytelen beszúrása a céltáblába. Ez akkor fordulhat elő, ha a forrástábla olyan sort tartalmaz, amely nem egy cél kötegben volt, hanem a teljes céltáblában volt. A helyes eredmények biztosítása:
-
ONA záradék segítségével meghatározhatja, hogy mely forrássorok érintik a meglévő célsorokat, és melyek valóban újak. - A záradék egy
WHEN MATCHEDtovábbi feltételével állapítsa meg, hogy a célsort már frissítette-e egy korábbi köteg. - Használjon egy további feltételt a záradékban és
WHEN MATCHEDaSETlogikában annak ellenőrzéséhez, hogy ugyanazt a sort nem lehet kétszer frissíteni.
-
Mivel a TOP záradék csak a záradékok alkalmazása után lesz alkalmazva, minden végrehajtás vagy beszúr egy valóban nem egyező sort, vagy frissít egy meglévő sort.
Ajánlott tömeges betöltési eljárások
Az MERGE utasítással hatékonyan tölthetők be adatok egy forrásadatfájlból egy céltáblába a OPENROWSET(BULK...) záradék táblaforrásként való megadásával. Ezzel a teljes fájl egyetlen kötegben lesz feldolgozva.
A tömeges egyesítési folyamat teljesítményének javítása érdekében az alábbi irányelveket javasoljuk:
Hozzon létre egy fürtözött indexet a céltábla illesztőoszlopaiban.
Tiltsa le a céltábla egyéb nem egyedi, nemclustered indexeit a tömeges betöltés
MERGEsorán, majd engedélyezze őket. Ez gyakori és hasznos éjszakai tömeges adatműveletek esetén.ORDERA záradékban találhatóUNIQUEtippeket ésOPENROWSET(BULK...)tippeket használva adja meg a forrásadatfájl rendezésének módját.Alapértelmezés szerint a tömeges művelet feltételezi, hogy az adatfájl rendezetlen. Ezért fontos, hogy a forrásadatok a céltábla fürtözött indexe szerint legyen rendezve, és hogy a
ORDERtipp a sorrend jelzésére szolgáljon, hogy a lekérdezésoptimalizáló hatékonyabb lekérdezéstervet hozhasson létre. A tippek futásidőben lesznek érvényesítve; ha az adatfolyam nem felel meg a megadott tippeknek, hibaüzenet jelenik meg.
Ezek az irányelvek biztosítják, hogy az illesztési kulcsok egyediek legyenek, és a forrásfájlban lévő adatok rendezési sorrendje megegyezik a céltáblával. A lekérdezési teljesítmény javul, mert nincs szükség további rendezési műveletekre, és nincs szükség szükségtelen adatmásolatokra.
A MERGE teljesítményének mérése és diagnosztizálása
Az alábbi funkciók segítenek az utasítások teljesítményének mérésében és diagnosztizálásában MERGE .
- A sys.dm_exec_query_optimizer_info dinamikus felügyeleti nézetben az egyesítési stmt számlálóval adja vissza az utasításokhoz tartozó
MERGElekérdezésoptimalizálások számát. - Használja az attribútumot a
merge_action_typesys.dm_exec_plan_attributes dinamikus felügyeleti nézetben az utasítás eredményeként használt trigger-végrehajtási terv típusánakMERGEvisszaadásához. - A kiterjesztett események munkamenetével ugyanúgy gyűjthet hibaelhárítási adatokat az
MERGEutasításhoz, mint más adatmanipulációs nyelvi (DML-) utasítások esetében. A Bővített események áttekintése további információkért lásd a Rövid útmutatót – Bővített események, és a SSMS XEvent Profilerhasználata című részt.
Examples
A. A MERGE használatával egyetlen utasításban hajthat végre beszúrási és FRISSÍTÉSi műveleteket egy táblán
Gyakori forgatókönyv egy tábla egy vagy több oszlopának frissítése, ha létezik egyező sor. Vagy új sorként is beszúrhatja az adatokat, ha egyező sor nem létezik. Általában mindkét forgatókönyvet úgy hajtja végre, hogy paramétereket ad át egy tárolt eljárásnak, amely tartalmazza a megfelelő UPDATE és INSERT az utasításokat. Az utasítással MERGE mindkét feladatot egyetlen utasításban végezheti el. Az alábbi példa egy AdventureWorks2025 adatbázisban tárolt eljárást mutat, amely mind egy INSERT utasítást, mind egy UPDATE utasítást tartalmaz. Ezt követően a rendszer úgy módosítja az eljárást, hogy egyetlen utasítással MERGE futtassa az egyenértékű műveleteket.
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. A MERGE használatával egyetlen utasításban hajthat végre FRISSÍTÉSi és TÖRLÉSi műveleteket egy táblán
A következő példa MERGE naponta frissíti a ProductInventory táblázatot az AdventureWorks2025 mintaadatbázisban, a táblázatban feldolgozott SalesOrderDetail megrendelések alapján. A Quantity tábla oszlopa úgy ProductInventory frissül, hogy kivonja az egyes termékekre naponta leadott rendelések számát a SalesOrderDetail táblában. Ha egy termék rendeléseinek száma egy termék készletszintje 0-ra vagy annál kisebbre csökken, a termék sorát a rendszer törli a ProductInventory táblából.
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. A MERGE használatával update és INSERT műveleteket hajthat végre egy céltáblán egy származtatott forrástáblával
A következő példa MERGE az AdventureWorks2025 adatbázisban a SalesReason táblázat módosítására szolgál sorok frissítésével vagy hozzáadásával.
Ha a forrástábla értéke NewName megegyezik a Name céltábla oszlopában lévő értékkel, azSalesReasonReasonType oszlop frissül a céltáblában. Ha az érték NewName nem egyezik, a forrássor be lesz szúrva a céltáblába. A forrástábla egy származtatott tábla, amely a Transact-SQL tábla értékkonstruktorával több sort ad meg a forrástábla számára. A táblaérték-konstruktor származtatott táblában való használatáról további információt a Table Value Constructor (Transact-SQL) című témakörben talál.
A OUTPUT záradék hasznos lehet az utasítások eredményének MERGE lekérdezéséhez. További információ: OUTPUT záradék (Transact-SQL). A példa azt is bemutatja, hogyan tárolhatja a OUTPUT záradék eredményeit egy táblaváltozóban. Ezután összegzi az MERGE utasítás eredményeit egy egyszerű kiválasztási művelet futtatásával, amely visszaadja a beszúrt és frissített sorok számát.
-- 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;
Ha a forrástábla értéke NewName megegyezik a Name céltábla oszlopában lévő értékkel, azSalesReasonReasonType oszlop frissül a céltáblában. Ha az érték NewName nem egyezik, a forrássor be lesz szúrva a céltáblába. A forrástábla egy származtatott tábla, amely a forrástábla több sorának megadására használható SELECT ... UNION ALL .
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. A MERGE utasítás eredményeinek beszúrása egy másik táblába
Az alábbi példa egy OUTPUT utasítás záradékából MERGE visszaadott adatokat rögzíti, és beszúrja az adatokat egy másik táblába. Az MERGE állítás frissíti a Quantity táblázat oszlopát ProductInventory az AdventureWorks2025 adatbázisban, a táblázatban feldolgozott SalesOrderDetail rendelések alapján. A példa rögzíti a frissített sorokat, és beszúrja őket egy másik táblába, amely a készletváltozások nyomon követésére szolgál.
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. A MERGE használatával szúrhat be vagy frissíthet egy gráfadatbázis cél éltábláján
Ebben a példában csomóponttáblákat Person és City egy éltáblát livesInhoz létre. Az élen lévő MERGElivesIn utasítást használva szúrjon be egy új sort, ha az él még nem létezik az és PersonCity a között. Ha az él már létezik, akkor csak frissítse a StreetAddress attribútumot a livesIn peremhálózaton.
-- 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