MERGE (Transact-SQL)MERGE (Transact-SQL)

適用対象: yesSQL Server yesAzure SQL Database noAzure Synapse Analytics (SQL DW) noParallel Data Warehouse APPLIES TO: yesSQL Server yesAzure SQL Database noAzure Synapse Analytics (SQL DW) noParallel Data Warehouse

ソース テーブルとの結合結果から、挿入、更新、または削除操作を対象テーブルに対して実行します。Runs insert, update, or delete operations on a target table from the results of a join with a source table. たとえば、他のテーブルとの違いに基づいて、あるテーブル内の行を挿入、更新、または削除することにより、2 つのテーブルを同期します。For example, synchronize two tables by inserting, updating, or deleting rows in one table based on differences found in the other table.

パフォーマンスのヒント: 説明した MERGE ステートメントの条件付きの動作は、一致する特性が 2 つのテーブルで複雑に組み合わされている場合に最適です。Performance Tip: The conditional behavior described for the MERGE statement works best when the two tables have a complex mixture of matching characteristics. たとえば、存在しない場合は行を挿入し、一致しない場合は行を更新します。For example, inserting a row if it doesn't exist, or updating a row if it matches. 別のテーブルの行に基づいて 1 つのテーブルを更新するだけで、基本的な INSERT、UPDATE、および DELETE ステートメントのパフォーマンスとスケーラビリティが向上します。When simply updating one table based on the rows of another table, improve the performance and scalability with basic INSERT, UPDATE, and DELETE statements. 例:For example:

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

トピック リンク アイコン Transact-SQL 構文表記規則Topic link icon Transact-SQL Syntax Conventions

構文Syntax

[ WITH <common_table_expression> [,...n] ]  
MERGE
    [ TOP ( expression ) [ PERCENT ] ]
    [ INTO ] <target_table> [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]  
    USING <table_source>
    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 . ]  
  target_table  
}  
  
<merge_hint>::=  
{  
    { [ <table_hint_limited> [ ,...n ] ]  
    [ [ , ] INDEX ( index_val [ ,...n ] ) ] }  
}  
  
<table_source> ::=
{  
    table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ]
        [ WITH ( table_hint [ [ , ]...n ] ) ]
  | rowset_function [ [ AS ] table_alias ]
        [ ( bulk_column_alias [ ,...n ] ) ]
  | user_defined_function [ [ AS ] table_alias ]  
  | OPENXML <openxml_clause>
  | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]
  | <joined_table>
  | <pivoted_table>
  | <unpivoted_table>
}  
  
<merge_search_condition> ::=  
    <search_condition>  
  
<merge_matched>::=  
    { UPDATE SET <set_clause> | DELETE }  
  
<set_clause>::=  
SET  
  { column_name = { expression | DEFAULT | NULL }  
  | { udt_column_name.{ { property_name = expression  
                        | field_name = expression }  
                        | method_name ( argument [ ,...n ] ) }  
    }  
  | column_name { .WRITE ( expression , @Offset , @Length ) }  
  | @variable = expression  
  | @variable = column = expression  
  | column_name { += | -= | *= | /= | %= | &= | ^= | |= } expression  
  | @variable { += | -= | *= | /= | %= | &= | ^= | |= } expression  
  | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression  
  } [ ,...n ]
  
<merge_not_matched>::=  
{  
    INSERT [ ( column_list ) ]
        { VALUES ( values_list )  
        | DEFAULT VALUES }  
}  
  
<clause_search_condition> ::=  
    <search_condition>  
  
<search condition> ::=  
    MATCH(<graph_search_pattern>) | <search_condition_without_match> | <search_condition> AND <search_condition>

<search_condition_without_match> ::=
    { [ NOT ] <predicate> | ( <search_condition_without_match> )
    [ { AND | OR } [ NOT ] { <predicate> | ( <search_condition_without_match> ) } ]
[ ,...n ]  

<predicate> ::=
    { expression { = | < > | ! = | > | > = | ! > | < | < = | ! < } expression
    | string_expression [ NOT ] LIKE string_expression
  [ ESCAPE 'escape_character' ]
    | expression [ NOT ] BETWEEN expression AND expression
    | expression IS [ NOT ] NULL
    | CONTAINS
  ( { column | * } , '< contains_search_condition >' )
    | FREETEXT ( { column | * } , 'freetext_string' )
    | expression [ NOT ] IN ( subquery | expression [ ,...n ] )
    | expression { = | < > | ! = | > | > = | ! > | < | < = | ! < }
  { ALL | SOME | ANY} ( subquery )
    | EXISTS ( subquery ) }

<graph_search_pattern> ::=
    { <node_alias> {
                      { <-( <edge_alias> )- }
                    | { -( <edge_alias> )-> }
                    <node_alias>
                   }
    }
  
<node_alias> ::=
    node_table_name | node_table_alias

<edge_alias> ::=
    edge_table_name | edge_table_alias

<output_clause>::=  
{  
    [ OUTPUT <dml_select_list> INTO { @table_variable | output_table }  
        [ (column_list) ] ]  
    [ OUTPUT <dml_select_list> ]  
}  
  
<dml_select_list>::=  
    { <column_name> | scalar_expression }
        [ [AS] column_alias_identifier ] [ ,...n ]  
  
<column_name> ::=  
    { DELETED | INSERTED | from_table_name } . { * | column_name }  
    | $action  

引数Arguments

WITH <common_table_expression>WITH <common_table_expression>
MERGE ステートメントのスコープ内で定義された、一時的な名前付き結果セットまたはビュー (共通テーブル式とも呼ばれます) を指定します。Specifies the temporary named result set or view, also known as common table expression, that's defined within the scope of the MERGE statement. 結果セットは単純なクエリから派生し、MERGE ステートメントで参照されます。The result set derives from a simple query and is referenced by the MERGE statement. 詳細については、「WITH common_table_expression (Transact-SQL)」を参照してください。For more information, see WITH common_table_expression (Transact-SQL).

TOP ( expression ) [ PERCENT ]TOP ( expression ) [ PERCENT ]
影響を受ける行の数またはパーセンテージを指定します。Specifies the number or percentage of affected rows. expression には、行数または行のパーセンテージを指定できます。expression can be either a number or a percentage of the rows. TOP 式で参照される行は順序付けされません。The rows referenced in the TOP expression are not arranged in any order. 詳細については、「TOP (Transact-SQL)」を参照してください。For more information, see TOP (Transact-SQL).

TOP 句は、ソース テーブル全体と対象テーブル全体が結合され、挿入、更新、または削除操作の対象とならない結合された行が削除された後に適用されます。The TOP clause applies after the entire source table and the entire target table join and the joined rows that don't qualify for an insert, update, or delete action are removed. さらに、TOP 句は、結合された行の数を、指定した値に減らします。The TOP clause further reduces the number of joined rows to the specified value. 挿入、更新、または削除操作は、残りの結合された行に対して、順不同の方法で適用されます。The insert, update, or delete actions apply to the remaining joined rows in an unordered way. つまり、WHEN 句に定義された操作に行が割り当てられる順序は決まっていません。That is, there's no order in which the rows are distributed among the actions defined in the WHEN clauses. たとえば、TOP (10) を指定すると、10 行が影響を受けます。For example, specifying TOP (10) affects 10 rows. これらの行では、7 行が更新されて 3 行が挿入される場合も、1 行が削除され、5 行が更新され、4 行が挿入される場合もあります。Of these rows, 7 may be updated and 3 inserted, or 1 may be deleted, 5 updated, and 4 inserted, and so on.

MERGE ステートメントはソース テーブルと対象テーブルの両方のフル テーブル スキャンを実行するので、TOP 句を使用し、複数のバッチを作成して大きなテーブルを変更すると、I/O パフォーマンスが影響を受ける場合があります。Because the MERGE statement does a full table scan of both the source and target tables, I/O performance is sometimes affected when using the TOP clause to modify a large table by creating multiple batches. このシナリオでは、連続するすべてのバッチで確実に新しい行が対象になっていることが重要です。In this scenario, it's important to ensure that all successive batches target new rows.

database_namedatabase_name
target_table があるデータベースの名前です。The name of the database in which target_table is located.

schema_nameschema_name
target_table が属しているスキーマの名前です。The name of the schema to which target_table belongs.

target_tabletarget_table
<clause_search_condition> に基づいて <table_source> のデータ行が照合されるテーブルまたはビューです。The table or view against which the data rows from <table_source> are matched based on <clause_search_condition>. target_table は、MERGE ステートメントの WHEN 句で指定された挿入、更新、削除のいずれかの操作の対象です。target_table is the target of any insert, update, or delete operations specified by the WHEN clauses of the MERGE statement.

target_table がビューの場合、これに対するアクションはビューの更新条件を満たす必要があります。If target_table is a view, any actions against it must satisfy the conditions for updating views. 詳細については、「ビューを使用したデータ変更」を参照してください。For more information, see Modify Data Through a View.

target_table にリモート テーブルを指定することはできません。target_table can't be a remote table. target_table に対してルールを定義することはできません。target_table can't have any rules defined on it.

[ AS ] table_alias[ AS ] table_alias
テーブルを参照するための代替名です。An alternative name to reference a table.

USING <table_source>USING <table_source>
<merge_search condition> に基づいて target_table 内のデータ行と照合するデータ ソースを指定します。Specifies the data source that's matched with the data rows in target_table based on <merge_search condition>. この照合結果によって、MERGE ステートメントの WHEN 句で実行される操作が決まります。The result of this match dictates the actions to take by the WHEN clauses of the MERGE statement. <table_source> には、リモート テーブルを指定することも、リモート テーブルにアクセスする派生テーブルを指定することもできます。<table_source> can be a remote table or a derived table that accesses remote tables.

<table_source> には派生テーブルを指定できます。このテーブルでは、複数の行を指定してテーブルを作成する Transact-SQLTransact-SQL テーブル値コンストラクターを使用します。<table_source> can be a derived table that uses the Transact-SQLTransact-SQL table value constructor to construct a table by specifying multiple rows.

この句の構文および引数の詳細については、「FROM (Transact-SQL)」を参照してください。For more information about the syntax and arguments of this clause, see FROM (Transact-SQL).

ON <merge_search_condition>ON <merge_search_condition>
<table_source> と target_table を結合するための一致箇所を特定する条件を指定します。Specifies the conditions on which <table_source> joins with target_table to determine where they match.

注意事項

照合目的で使用する対象テーブルの列だけを指定することが重要です。It's important to specify only the columns from the target table to use for matching purposes. つまり、対象テーブルのうち、ソース テーブルの対応する列と比較する列を指定します。That is, specify columns from the target table that are compared to the corresponding column of the source table. AND NOT target_table.column_x = value と指定するなど、ON 句で対象テーブル内の行にフィルターを適用することによって、クエリ パフォーマンスを向上させようとしないでください。Don't attempt to improve query performance by filtering out rows in the target table in the ON clause; for example, such as specifying AND NOT target_table.column_x = value. この場合、予期しない無効な結果が返されることがあります。Doing so may return unexpected and incorrect results.

WHEN MATCHED THEN <merge_matched>WHEN MATCHED THEN <merge_matched>
<table_source> ON <merge_search_condition> で返される行に一致し、追加の検索条件を満たす *target_table のすべての行を、<merge_matched> 句に従って更新または削除するように指定します。Specifies that all rows of *target_table, which match the rows returned by <table_source> ON <merge_search_condition>, and satisfy any additional search condition, are either updated or deleted according to the <merge_matched> clause.

MERGE ステートメントには、最大 2 つの WHEN MATCHED 句を指定できます。The MERGE statement can have, at most, two WHEN MATCHED clauses. 句を 2 つ指定する場合、最初の句は AND <search_condition> 句と共に使用する必要があります。If two clauses are specified, the first clause must be accompanied by an AND <search_condition> clause. 任意の行に対し、最初の WHEN MATCHED 句が適用されなかった場合にのみ、2 番目の WHEN MATCHED 句が適用されます。For any given row, the second WHEN MATCHED clause is only applied if the first isn't. WHEN MATCHED 句が 2 つある場合は、一方で UPDATE 操作を、もう一方で DELETE 操作を指定する必要があります。If there are two WHEN MATCHED clauses, one must specify an UPDATE action and one must specify a DELETE action. <merge_matched> 句で UPDATE が指定されており、<merge_search_condition> に基づいて <table_source> の複数の行が target_table の 1 つの行に一致する場合、SQL ServerSQL Server からエラーが返されます。When UPDATE is specified in the <merge_matched> clause, and more than one row of <table_source> matches a row in target_table based on <merge_search_condition>, SQL ServerSQL Server returns an error. MERGE ステートメントで、同じ行を複数回更新することや、同じ行の更新と削除を行うことはできません。The MERGE statement can't update the same row more than once, or update and delete the same row.

WHEN NOT MATCHED [ BY TARGET ] THEN <merge_not_matched>WHEN NOT MATCHED [ BY TARGET ] THEN <merge_not_matched>
<table_source> ON <merge_search_condition> で返される行のうち、target_table 内の行とは一致しないが、追加の検索条件 (存在する場合) は満たす行ごとに、target_tableに 1 行を挿入するように指定します。Specifies that a row is inserted into target_table for every row returned by <table_source> ON <merge_search_condition> that doesn't match a row in target_table, but satisfies an additional search condition, if present. 挿入する値は、<merge_not_matched> 句で指定します。The values to insert are specified by the <merge_not_matched> clause. MERGE ステートメントに指定できる WHEN NOT MATCHED [ BY TARGET ] 句は 1 つだけです。The MERGE statement can have only one WHEN NOT MATCHED [ BY TARGET ] clause.

WHEN NOT MATCHED BY SOURCE THEN <merge_matched>WHEN NOT MATCHED BY SOURCE THEN <merge_matched>
<table_source> ON <merge_search_condition> で返される行には一致しないが、追加の検索条件は満たす <target_table のすべての行を、merge_matched> 句に従って更新または削除するように指定します。Specifies that all rows of *target_table, which don't match the rows returned by <table_source> ON <merge_search_condition>, and that satisfy any additional search condition, are updated or deleted according to the <merge_matched> clause.

MERGE ステートメントには、最大 2 つの WHEN NOT MATCHED BY SOURCE 句を指定できます。The MERGE statement can have at most two WHEN NOT MATCHED BY SOURCE clauses. 句を 2 つ指定する場合、最初の句は AND <clause_search_condition> 句と共に使用する必要があります。If two clauses are specified, then the first clause must be accompanied by an AND <clause_search_condition> clause. 任意の行に対し、最初の WHEN NOT MATCHED BY SOURCE 句が適用されなかった場合にのみ、2 番目の WHEN NOT MATCHED BY SOURCE 句が適用されます。For any given row, the second WHEN NOT MATCHED BY SOURCE clause is only applied if the first isn't. WHEN NOT MATCHED BY SOURCE 句が 2 つある場合は、一方で UPDATE 操作を、もう一方で DELETE 操作を指定する必要があります。If there are two WHEN NOT MATCHED BY SOURCE clauses, then one must specify an UPDATE action and one must specify a DELETE action. <clause_search_condition> では対象テーブルの列のみを参照できます。Only columns from the target table can be referenced in <clause_search_condition>.

<table_source> から返される行がない場合、ソース テーブルの列にアクセスすることはできません。When no rows are returned by <table_source>, columns in the source table can't be accessed. <merge_matched> 句に指定した更新操作または削除操作でソース テーブルの列を参照していると、エラー 207 (無効な列名) が返されます。If the update or delete action specified in the <merge_matched> clause references columns in the source table, error 207 (Invalid column name) is returned. たとえば、ソース テーブルの WHEN NOT MATCHED BY SOURCE THEN UPDATE SET TargetTable.Col1 = SourceTable.Col1 にアクセスできないために、Col1 句によってステートメントが失敗することがあります。For example, the clause WHEN NOT MATCHED BY SOURCE THEN UPDATE SET TargetTable.Col1 = SourceTable.Col1 may cause the statement to fail because Col1 in the source table is inaccessible.

AND <clause_search_condition>AND <clause_search_condition>
任意の有効な検索条件を指定します。Specifies any valid search condition. 詳しくは、「検索条件 (Transact-SQL)」をご覧ください。For more information, see Search Condition (Transact-SQL).

<table_hint_limited><table_hint_limited>
MERGE ステートメントによって実行される挿入、更新、削除の各操作に対し、対象テーブルに適用される 1 つ以上のテーブル ヒントを指定します。Specifies one or more table hints to apply on the target table for each of the insert, update, or delete actions done by the MERGE statement. キーワード WITH とかっこが必要です。The WITH keyword and the parentheses are required.

NOLOCK および READUNCOMMITTED は指定できません。NOLOCK and READUNCOMMITTED aren't allowed. テーブル ヒントの詳細については、「テーブル ヒント (Transact-SQL)」を参照してください。For more information about table hints, see Table Hints (Transact-SQL).

INSERT ステートメントの対象であるテーブルに対して TABLOCK ヒントを指定すると、TABLOCKX ヒントを指定した場合と同じ効果を得られます。Specifying the TABLOCK hint on a table that's the target of an INSERT statement has the same effect as specifying the TABLOCKX hint. テーブルに対して、排他ロックが取得されます。An exclusive lock is taken on the table. FORCESEEK を指定すると、ソース テーブルに結合された対象テーブルの暗黙のインスタンスに対して適用されます。When FORCESEEK is specified, it applies to the implicit instance of the target table joined with the source table.

注意事項

WHEN NOT MATCHED [ BY TARGET ] THEN INSERT に READPAST を指定すると、UNIQUE 制約に違反する INSERT 操作が発生する場合があります。Specifying READPAST with WHEN NOT MATCHED [ BY TARGET ] THEN INSERT may result in INSERT operations that violate UNIQUE constraints.

INDEX ( index_val [ ,...n ] )INDEX ( index_val [ ,...n ] )
ソース テーブルとの暗黙の結合を実行するための、対象テーブルの 1 つ以上のインデックスの名前または ID を指定します。Specifies the name or ID of one or more indexes on the target table for doing an implicit join with the source table. 詳細については、「テーブル ヒント (Transact-SQL)」を参照してください。For more information, see Table Hints (Transact-SQL).

<output_clause><output_clause>
target_table 内の更新、挿入、または削除される行ごとに 1 行を返します。この場合、特定の順序はありません。Returns a row for every row in target_table that's updated, inserted, or deleted, in no particular order. $action は、OUTPUT 句に指定することができます。$action can be specified in the output clause. $action は、行に対して実行されたアクションに従って次のいずれかの値をそれぞれの行について返す、nvarchar(10) 型の列です:"INSERT"、"UPDATE"、または "DELETE"。その行で実行されるアクションに従います。$action is a column of type nvarchar(10) that returns one of three values for each row: 'INSERT', 'UPDATE', or 'DELETE', according to the action done on that row. この句の引数について詳しくは、「OUTPUT Clause (Transact-SQL)」をご覧ください。For more information about the arguments of this clause, see OUTPUT Clause (Transact-SQL).

OPTION ( <query_hint> [ ,...n ] )OPTION ( <query_hint> [ ,...n ] )
オプティマイザー ヒントを使用して、データベース エンジンがステートメントを処理する方法をカスタマイズすることを指定します。Specifies that optimizer hints are used to customize the way the Database Engine processes the statement. 詳細については、「クエリ ヒント (Transact-SQL)」を参照してください。For more information, see Query Hints (Transact-SQL).

<merge_matched><merge_matched>
<table_source> ON <merge_search_condition> で返される行には一致しないが、追加の検索条件は満たす target_table のすべての行に対して適用する更新操作または削除操作を指定します。Specifies the update or delete action that's applied to all rows of target_table that don't match the rows returned by <table_source> ON <merge_search_condition>, and which satisfy any additional search condition.

UPDATE SET <set_clause>UPDATE SET <set_clause>
対象テーブル内で更新する列名または変数名の一覧と、それらの更新に使用する値を指定します。Specifies the list of column or variable names to update in the target table and the values with which to update them.

この句の引数について詳しくは、「UPDATE (Transact-SQL)」をご覧ください。For more information about the arguments of this clause, see UPDATE (Transact-SQL). 列と同じ値を変数に設定することはできません。Setting a variable to the same value as a column isn't supported.

DELETEDELETE
target_table 内の行に一致する行を削除するように指定します。Specifies that the rows matching rows in target_table are deleted.

<merge_not_matched><merge_not_matched>
対象テーブルに挿入する値を指定します。Specifies the values to insert into the target table.

(column_list)(column_list)
対象テーブルのデータを挿入する 1 つ以上の列で構成されるリストを指定します。A list of one or more columns of the target table in which to insert data. 列は 1 部構成の名前で指定する必要があります。そうしないと MERGE ステートメントが失敗します。Columns must be specified as a single-part name or else the MERGE statement will fail. column_list はかっこで囲み、コンマで区切る必要があります。column_list must be enclosed in parentheses and delimited by commas.

VALUES ( values_list)VALUES ( values_list)
対象テーブルに挿入する値を返す定数、変数、または式を、コンマ区切りのリストで指定します。A comma-separated list of constants, variables, or expressions that return values to insert into the target table. 式に EXECUTE ステートメントを含めることはできません。Expressions can't contain an EXECUTE statement.

DEFAULT VALUESDEFAULT VALUES
挿入される行が、各列に対して定義されている既定値で構成されることを指定します。Forces the inserted row to contain the default values defined for each column.

この句について詳しくは、「INSERT (Transact-SQL)」をご覧ください。For more information about this clause, see INSERT (Transact-SQL).

<search condition><search condition>
<merge_search_condition> または <clause_search_condition> を指定する検索条件を指定します。Specifies the search conditions to specify <merge_search_condition> or <clause_search_condition>. この句の引数について詳しくは、「検索条件 (Transact-SQL)」をご覧ください。For more information about the arguments for this clause, see Search Condition (Transact-SQL).

<graph search pattern><graph search pattern>
グラフの一致パターンを指定します。Specifies the graph match pattern. この句の引数の詳細については、「MATCH (Transact-SQL)」を参照してくださいFor more information about the arguments for this clause, see MATCH (Transact-SQL)

RemarksRemarks

3 つの MATCHED 句のうち、少なくとも 1 つは指定する必要があります。これらの句は、任意の順序で指定できます。At least one of the three MATCHED clauses must be specified, but they can be specified in any order. 1 つの MATCHED 句で 1 つの変数を複数回更新することはできません。A variable can't be updated more than once in the same MATCHED clause.

MERGE ステートメントによって対象テーブルに指定された挿入、更新、削除の各操作は、連鎖参照整合性制約など、定義されている制約の制限を受けます。Any insert, update, or delete action specified on the target table by the MERGE statement are limited by any constraints defined on it, including any cascading referential integrity constraints. 対象テーブルの一意インデックスで IGNORE_DUP_KEY が ON に設定されていると、MERGE ではこの設定が無視されます。If IGNORE_DUP_KEY is ON for any unique indexes on the target table, MERGE ignores this setting.

MERGE ステートメントでは、ステートメントのターミネータとしてセミコロン (;) が必要です。The MERGE statement requires a semicolon (;) as a statement terminator. MERGE ステートメントにターミネータを付けずに実行すると、エラー 10713 が生成されます。Error 10713 is raised when a MERGE statement is run without the terminator.

MERGE の後に @@ROWCOUNT (Transact-SQL) を使用すると、クライアントに対して挿入、更新、および削除された行の合計数が返されます。When used after MERGE, @@ROWCOUNT (Transact-SQL) returns the total number of rows inserted, updated, and deleted to the client.

データベースの互換性レベルが 100 以上に設定されている場合、MERGE は完全に予約されたキーワードです。MERGE is a fully reserved keyword when the database compatibility level is set to 100 or higher. MERGE ステートメントはデータベースの互換性レベルが 90 と 100 の両方で使用できますが、データベースの互換性レベルが 90 に設定されている場合、MERGE キーワードは完全には予約されません。The MERGE statement is available under both 90 and 100 database compatibility levels; however, the keyword isn't fully reserved when the database compatibility level is set to 90.

MERGE ステートメントは、キュー更新レプリケーションの使用時には使用しないでください。Don't use the MERGE statement when using queued updating replication. MERGE とキュー更新トリガーには互換性がありません。The MERGE and queued updating trigger aren't compatible. MERGE ステートメントは、挿入ステートメントまたは更新ステートメントと置き換えてください。Replace the MERGE statement with an insert or an update statement.

トリガーの実装Trigger Implementation

MERGE ステートメントに指定された挿入、更新、削除の各操作に対し、対象テーブルで定義された対応する AFTER トリガーが SQL ServerSQL Server によって起動されますが、どの操作に対するトリガーからどのような順序で起動されるかは決まっていません。For every insert, update, or delete action specified in the MERGE statement, SQL ServerSQL Server fires any corresponding AFTER triggers defined on the target table, but doesn't guarantee on which action to fire triggers first or last. 同じ操作に対して定義された複数のトリガーは、指定した順序に従います。Triggers defined for the same action honor the order you specify. トリガー起動順序の設定の詳細については、「最初と最後のトリガーの指定」を参照してください。For more information about setting trigger firing order, see Specify First and Last Triggers.

MERGE ステートメントによって実行される挿入、更新、削除のいずれかの操作に対して、有効な INSTEAD OF トリガーが対象テーブルに定義されている場合、MERGE ステートメントに指定されたすべての操作に有効な INSTEAD OF トリガーを定義する必要があります。If the target table has an enabled INSTEAD OF trigger defined on it for an insert, update, or delete action done by a MERGE statement, it must have an enabled INSTEAD OF trigger for all of the actions specified in the MERGE statement.

INSTEAD OF UPDATE トリガーや INSTEAD OF DELETE トリガーが target_table に定義されている場合、更新操作や削除操作は実行されません。If any INSTEAD OF UPDATE or INSTEAD OF DELETE triggers are defined on target_table, the update or delete operations aren't run. 代わりにトリガーが起動され、inserted テーブルと deleted テーブルに適切なデータが設定されます。Instead, the triggers fire and the inserted and deleted tables then populate accordingly.

INSTEAD OF INSERT トリガーが target_table に定義されている場合、挿入操作は実行されません。If any INSTEAD OF INSERT triggers are defined on target_table, the insert operation isn't performed. 代わりに、テーブルに適切なデータが設定されます。Instead, the table populates accordingly.

アクセス許可Permissions

ソース テーブルに対する SELECT 権限と、対象テーブルに対する INSERT、UPDATE、または DELETE 権限が必要です。Requires SELECT permission on the source table and INSERT, UPDATE, or DELETE permissions on the target table. 詳しくは、「SELECT」、「INSERT」、「UPDATE」、「DELETE」の各記事の「権限」をご覧ください。For more information, see the Permissions section in the SELECT, INSERT, UPDATE, and DELETE articles.

MERGE ステートメントのパフォーマンスの最適化Optimizing MERGE Statement Performance

MERGE ステートメントを使用すると、個々の DML ステートメントを単一のステートメントに置き換えることができます。By using the MERGE statement, you can replace the individual DML statements with a single statement. これにより、操作が単一のステートメント内で実行されてソース テーブルと対象テーブルのデータの処理回数が最小限に抑えられるので、クエリのパフォーマンスが向上します。This can improve query performance because the operations are performed within a single statement, therefore, minimizing the number of times the data in the source and target tables are processed. ただし、パフォーマンスが向上するかどうかは、インデックスが正しいか、結合が存在するかなど、いくつかの考慮事項によって決まります。However, performance gains depend on having correct indexes, joins, and other considerations in place.

インデックスに関するベスト プラクティスIndex Best Practices

MERGE ステートメントのパフォーマンスを向上させるには、次のインデックスのガイドラインに従うことをお勧めします。To improve the performance of the MERGE statement, we recommend the following index guidelines:

  • ソース テーブルの結合列に一意なカバリング インデックスを作成します。Create an index on the join columns in the source table that is unique and covering.
  • 対象テーブルの結合列に一意なクラスター化インデックスを作成します。Create a unique clustered index on the join columns in the target table.

これらのインデックスによって結合キーが一意になり、テーブルのデータが並べ替えられるようになります。These indexes ensure that the join keys are unique and the data in the tables is sorted. クエリ オプティマイザーが重複行を見つけて更新するために追加の検証処理を実行する必要がなく、追加の並べ替え操作が不要になるので、クエリのパフォーマンスが向上します。Query performance is improved because the query optimizer does not need to perform extra validation processing to locate and update duplicate rows and additional sort operations are not necessary.

JOIN に関するベスト プラクティスJOIN Best Practices

MERGE ステートメントのパフォーマンスを向上させて正しい結果が得られるようにするには、次の結合のガイドラインに従うことをお勧めします。To improve the performance of the MERGE statement and ensure correct results are obtained, we recommend the following join guidelines:

  • <merge_search_condition> 句で、ソース テーブルと対象テーブルのデータを照合する基準を判断する検索条件のみを指定します。Specify only search conditions in the ON <merge_search_condition> clause that determine the criteria for matching data in the source and target tables. つまり、対象テーブルのうち、ソース テーブル内の対応する列と比較する列のみを指定します。That is, specify only columns from the target table that are compared to the corresponding columns of the source table.
  • 定数などのその他の値との比較は指定しないでください。Do not include comparisons to other values such as a constant.

ソース テーブルまたは対象テーブルから行を除外するには、次のいずれかの方法を使用します。To filter out rows from the source or target tables, use one of the following methods.

  • 適切な WHEN 句で、行をフィルター選択するための検索条件を指定します。Specify the search condition for row filtering in the appropriate WHEN clause. たとえば、WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT... のようにします。For example, WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT....
  • フィルター選択された行を返すソースまたは対象のビューを定義して、そのビューをソース テーブルまたは対象テーブルとして参照します。Define a view on the source or target that returns the filtered rows and reference the view as the source or target table. ビューが対象テーブルに対して定義されている場合、これに対するアクションはビューの更新条件を満たす必要があります。If the view is defined on the target table, any actions against it must satisfy the conditions for updating views. ビューを使用してデータを更新する方法の詳細については、「ビューを使用したデータ変更」を参照してください。For more information about updating data by using a view, see Modifying Data Through a View.
  • WITH <common table expression> 句を使用して、ソース テーブルまたは対象テーブルから行を除外します。Use the WITH <common table expression> clause to filter out rows from the source or target tables. この方法は、ON 句で追加の検索条件を指定する方法に似ており、不適切な結果が返される可能性があります。This method is similar to specifying additional search criteria in the ON clause and may produce incorrect results. この方法を使用しないようにするか、十分にテストしてから実装することをお勧めします。We recommend that you avoid using this method or test thoroughly before implementing it.

MERGE ステートメントでの結合操作は、SELECT ステートメントでの結合と同じ方法で最適化されます。The join operation in the MERGE statement is optimized in the same way as a join in a SELECT statement. つまり、SQL Server で結合を処理する場合、クエリ オプティマイザーは、複数の候補の中から最も効率的な結合の処理方法を選択します。That is, when SQL Server processes joins, the query optimizer chooses the most efficient method (out of several possibilities) of processing the join. ソースと対象が同じようなサイズで、前に説明したインデックスのガイドラインがソース テーブルと対象テーブルに適用されている場合は、Merge Join 操作が最も効率的なクエリ プランになります。When the source and target are of similar size and the index guidelines described previously are applied to the source and target tables, a merge join operator is the most efficient query plan. これは、両方のテーブルが 1 回だけスキャンされ、データを並べ替える必要がないためです。This is because both tables are scanned once and there is no need to sort the data. ソース テーブルが対象テーブルよりも小さい場合は、Nested Loops 操作をお勧めします。When the source is smaller than the target table, a nested loops operator is preferable.

MERGE ステートメントで OPTION (<query_hint>) 句を指定することで、特定の結合を強制的に使用することができます。You can force the use of a specific join by specifying the OPTION (<query_hint>) clause in the MERGE statement. MERGE ステートメントのクエリ ヒントとしてハッシュ結合を使用しないことをお勧めします。この種類の結合ではインデックスが使用されないためです。We recommend that you do not use the hash join as a query hint for MERGE statements because this join type does not use indexes.

パラメーター化に関するベスト プラクティスParameterization Best Practices

パラメーターを指定せずに SELECT、INSERT、UPDATE、または DELETE ステートメントを実行した場合、SQL Server のクエリ オプティマイザーの内部でステートメントがパラメーター化される場合があります。If a SELECT, INSERT, UPDATE, or DELETE statement is executed without parameters, the SQL Server query optimizer may choose to parameterize the statement internally. これは、クエリに含まれるリテラル値がすべてパラメーターに置き換えられることを意味します。This means that any literal values that are contained in the query are substituted with parameters. たとえば、ステートメント INSERT dbo.MyTable (Col1, Col2) VALUES (1, 10) は、内部で INSERT dbo.MyTable (Col1, Col2) VALUES (@p1, @p2) と実装される場合があります。For example, the statement INSERT dbo.MyTable (Col1, Col2) VALUES (1, 10), may be implemented internally as INSERT dbo.MyTable (Col1, Col2) VALUES (@p1, @p2). 簡易パラメーター化と呼ばれるこの処理によって、新しい SQL ステートメントと既存のコンパイル済みの実行プランとを照合するリレーショナル エンジンの機能が向上します。This process, called simple parameterization, increases the ability of the relational engine to match new SQL statements with existing, previously-compiled execution plans. クエリをコンパイルおよび再コンパイルする頻度が下がるので、クエリのパフォーマンスが向上する場合があります。Query performance may be improved because the frequency of query compilations and recompilations are reduced. クエリ オプティマイザーでは、簡易パラメーター化処理は MERGE ステートメントには適用されません。The query optimizer does not apply the simple parameterization process to MERGE statements. したがって、MERGE ステートメントが実行されるたびに新しいプランがコンパイルされるので、リテラル値を含む MERGE ステートメントは、個々の INSERT、UPDATE、または DELETE ステートメントよりもパフォーマンスが低くなる可能性があります。Therefore, MERGE statements that contain literal values may not perform as well as individual INSERT, UPDATE, or DELETE statements because a new plan is compiled each time the MERGE statement is executed.

クエリのパフォーマンスを向上させるには、次のパラメーター化のガイドラインに従うことをお勧めします。To improve query performance, we recommend the following parameterization guidelines:

  • MERGE ステートメントの ON <merge_search_condition> 句と WHEN 句ですべてのリテラル値をパラメーター化します。Parameterize all literal values in the ON <merge_search_condition> clause and in the the WHEN clauses of the MERGE statement. たとえば、リテラル値を適切な入力パラメーターに置き換えるストアド プロシージャに MERGE ステートメントを組み込むことができます。For example, you can incorporate the MERGE statement into a stored procedure replacing the literal values with appropriate input parameters.
  • ステートメントをパラメーター化できない場合は、TEMPLATE 型のプラン ガイドを作成し、そのプラン ガイドで PARAMETERIZATION FORCED クエリ ヒントを指定します。If you cannot parameterize the statement, create a plan guide of type TEMPLATE and specify the PARAMETERIZATION FORCED query hint in the plan guide.
  • MERGE ステートメントがデータベースで頻繁に実行される場合は、データベースの PARAMETERIZATION オプションを FORCED に設定することを検討します。If MERGE statements are executed frequently on the database, consider setting the PARAMETERIZATION option on the database to FORCED. このオプションを設定する場合は注意が必要です。Use caution when setting this option. PARAMETERIZATION オプションはデータベース レベルの設定で、データベースに対するすべてのクエリの処理方法に影響します。The PARAMETERIZATION option is a database-level setting and affects how all queries against the database are processed.

TOP 句に関するベスト プラクティスTOP Clause Best Practices

MERGE ステートメントの TOP 句では、ソース テーブルと対象テーブルが結合され、挿入、更新、または削除操作の対象とならない行が削除された後に影響を受ける、行の数または割合を指定します。In the MERGE statement, the TOP clause specifies the number or percentage of rows that are affected after the source table and the target table are joined, and after rows that do not qualify for an insert, update, or delete action are removed. TOP 句を使用すると、結合された行の数が指定の値まで減少し、挿入、更新、または削除操作が残りの結合された行に順序付けなしで適用されます。The TOP clause further reduces the number of joined rows to the specified value and the insert, update, or delete actions are applied to the remaining joined rows in an unordered fashion. つまり、WHEN 句で定義された各操作に行を割り当てる順序に決まりはありません。That is, there is no order in which the rows are distributed among the actions defined in the WHEN clauses. たとえば、TOP (10) と指定すると 10 行に影響しますが、そのうち 7 行が更新されて 3 行が挿入される場合も、1 行が削除、5 行が更新され、4 行が挿入される場合もあります。For example, specifying TOP (10) affects 10 rows; of these rows, 7 may be updated and 3 inserted, or 1 may be deleted, 5 updated, and 4 inserted and so on.

一般に、TOP 句は、データ操作言語 (DML) 操作を大きなテーブルに対してバッチで実行するために使用します。It is common to use the TOP clause to perform data manipulation language (DML) operations on a large table in batches. このために MERGE ステートメントで TOP 句を使用する場合は、次の影響について理解しておくことが重要です。When using the TOP clause in the MERGE statement for this purpose, it is important to understand the following implications.

  • I/O のパフォーマンスに影響する場合があります。I/O performance may be affected.

    MERGE ステートメントでは、ソース テーブルと対象テーブルの両方のフル テーブル スキャンが実行されます。The MERGE statement performs a full table scan of both the source and target tables. 操作をバッチに分割すると、バッチごとに実行される書き込み操作の数は減少しますが、各バッチでソース テーブルと対象テーブルのフル テーブル スキャンが実行されます。Dividing the operation into batches reduces the number of write operations performed per batch; however, each batch will perform a full table scan of the source and target tables. 結果として行われる読み取り操作が、クエリのパフォーマンスに影響する場合があります。The resulting read activity may affect the performance of the query.

  • 不適切な結果になる可能性があります。Incorrect results can occur.

    一連のすべてのバッチが新しい行を対象としていることを確認してください。新しい行を対象としていない場合は、対象テーブルに重複行が誤って挿入されるなどの不適切な動作が発生する可能性があります。It is important to ensure that all successive batches target new rows or undesired behavior such as incorrectly inserting duplicate rows into the target table can occur. このような動作は、対象バッチには存在しないが対象テーブル全体には存在する行がソース テーブルに含まれている場合に発生する可能性があります。This can happen when the source table includes a row that was not in a target batch but was in the overall target table.

  • 正しい結果を得るには、次の操作を実行します。To insure correct results:

    • ON 句を使用して、既存の対象行に影響するソース行と本当に新しい行を特定します。Use the ON clause to determine which source rows affect existing target rows and which are genuinely new.
    • WHEN MATCHED 句で追加条件を使用して、対象行が以前のバッチで既に更新されているかどうかを調べます。Use an additional condition in the WHEN MATCHED clause to determine if the target row has already been updated by a previous batch.

TOP 句はこれらの句が適用された後にのみ適用されるので、実行ごとに本当に一致しない 1 行が挿入されるか、既存の 1 行が更新されます。Because the TOP clause is only applied after these clauses are applied, each execution either inserts one genuinely unmatched row or updates one existing row.

一括読み込みに関するベスト プラクティスBulk Load Best Practices

MERGE ステートメントを使用すると、OPENROWSET(BULK…) 句をテーブル ソースとして指定することによって、ソース データ ファイルから対象テーブルにデータを効率よく一括読み込みできます。The MERGE statement can be used to efficiently bulk load data from a source data file into a target table by specifying the OPENROWSET(BULK…) clause as the table source. これにより、ファイル全体が単一のバッチで処理されます。By doing so, the entire file is processed in a single batch.

一括マージ処理のパフォーマンスを向上させるには、次のガイドラインに従うことをお勧めします。To improve the performance of the bulk merge process, we recommend the following guidelines:

  • 対象テーブルの結合列にクラスター化インデックスを作成します。Create a clustered index on the join columns in the target table.

  • OPENROWSET(BULK…) 句で ORDER ヒントと UNIQUE ヒントを使用して、ソース データ ファイルの並べ替え方法を指定します。Use the ORDER and UNIQUE hints in the OPENROWSET(BULK…) clause to specify how the source data file is sorted.

    既定では、一括操作はデータ ファイルが並べ替えられていないことを前提に実行されます。By default, the bulk operation assumes the data file is unordered. そのため、ソース データが対象テーブルのクラスター化インデックスに従って並べ替えられることと、クエリ オプティマイザーでより効率的なクエリ プランを生成できるように ORDER ヒントを使用して順序を指定することが重要です。Therefore, it is important that the source data is sorted according to the clustered index on the target table and that the ORDER hint is used to indicate the order so that the query optimizer can generate a more efficient query plan. ヒントは実行時に検証されます。データ ストリームが指定されたヒントに適合していない場合は、エラーが発生します。Hints are validated at runtime; if the data stream does not conform to the specified hints, an error is raised.

これらのガイドラインによって結合キーが一意になり、ソース ファイルのデータの並べ替え順が対象テーブルと一致するようになります。These guidelines ensure that the join keys are unique and the sort order of the data in the source file matches the target table. 追加の並べ替え操作が不要になり、不要なデータのコピーが必要なくなるので、クエリのパフォーマンスが向上します。Query performance is improved because additional sort operations are not necessary and unnecessary data copies are not required.

MERGE のパフォーマンスの測定と診断Measuring and Diagnosing MERGE Performance

次の機能を使用すると、MERGE ステートメントのパフォーマンスの測定と診断に役立ちます。The following features are available to assist you in measuring and diagnosing the performance of MERGE statements.

  • sys.dm_exec_query_optimizer_info 動的管理ビューの merge stmt カウンターを使用すると、MERGE ステートメントに対するクエリの最適化の数が返されます。Use the merge stmt counter in the sys.dm_exec_query_optimizer_info dynamic management view to return the number of query optimizations that are for MERGE statements.
  • sys.dm_exec_plan_attributes 動的管理ビューの merge_action_type 属性を使用すると、MERGE ステートメントの結果として使用するトリガーの実行プランの種類が返されます。Use the merge_action_type attribute in the sys.dm_exec_plan_attributes dynamic management view to return the type of trigger execution plan used as the result of a MERGE statement.
  • SQL トレースを使用すると、MERGE ステートメントのトラブルシューティング データが、その他のデータ操作言語 (DML) ステートメントの場合と同じ方法で収集されます。Use SQL Trace to gather troubleshooting data for the MERGE statement in the same way you would for other data manipulation language (DML) statements. 詳細については、「 SQL Trace」を参照してください。For more information, see SQL Trace.

使用例Examples

A.A. MERGE を使用して、単一のステートメントでテーブルに INSERT 操作と UPDATE 操作を実行するUsing MERGE to do INSERT and UPDATE operations on a table in a single statement

一般的なシナリオは、一致する行が存在する場合、テーブル内の 1 つまたは複数の列を更新することです。A common scenario is updating one or more columns in a table if a matching row exists. または、一致する行が存在しない場合は、データを新しい行として挿入します。Or, inserting the data as a new row if a matching row doesn't exist. 通常は、適切な UPDATE ステートメントと INSERT ステートメントを含むストアド プロシージャにパラメーターを渡すことで、どちらかを実行します。You usually do either scenario by passing parameters to a stored procedure that contains the appropriate UPDATE and INSERT statements. MERGE ステートメントを使用すると、単一のステートメントで両方のタスクを実行できます。With the MERGE statement, you can do both tasks in a single statement. 次の例は、INSERT ステートメントと UPDATE ステートメントの両方を含む AdventureWorks2012AdventureWorks2012 データベースのストアド プロシージャを示しています。The following example shows a stored procedure in the AdventureWorks2012AdventureWorks2012database that contains both an INSERT statement and an UPDATE statement. このプロシージャを、単一の MERGE ステートメントで同等の操作を実行するように変更します。The procedure is then modified to run the equivalent operations by using a single MERGE statement.

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 target  
    USING (SELECT @UnitMeasureCode, @Name) AS source (UnitMeasureCode, Name)  
    ON (target.UnitMeasureCode = source.UnitMeasureCode)  
    WHEN MATCHED THEN
        UPDATE SET Name = source.Name  
    WHEN NOT MATCHED THEN  
        INSERT (UnitMeasureCode, Name)  
        VALUES (source.UnitMeasureCode, source.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  

B.B. MERGE を使用して、単一のステートメントでテーブルに UPDATE 操作と DELETE 操作を実行するUsing MERGE to do UPDATE and DELETE operations on a table in a single statement

次の例では、MERGE を使用して、ProductInventory テーブルで処理される注文に基づいて、AdventureWorks2012AdventureWorks2012 サンプル データベース内の SalesOrderDetail テーブルを毎日更新します。The following example uses MERGE to update the ProductInventory table in the AdventureWorks2012AdventureWorks2012 sample database, daily, based on orders that are processed in the SalesOrderDetail table. Quantity テーブルで各製品のその日の注文数を差し引くことで、ProductInventory テーブルの SalesOrderDetail 列を更新します。The Quantity column of the ProductInventory table is updated by subtracting the number of orders placed each day for each product in the SalesOrderDetail table. 製品の注文数によって、製品の在庫レベルが 0 以下に低下した場合は、その製品の行が ProductInventory テーブルから削除されます。If the number of orders for a product drops the inventory level of a product to 0 or less, the row for that product is deleted from the ProductInventory table.

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

C.C. MERGE で、派生ソース テーブルを使用して対象テーブルに UPDATE 操作と INSERT 操作を実行するUsing MERGE to do UPDATE and INSERT operations on a target table by using a derived source table

次の例は、MERGE を使用し、行を更新または挿入することで AdventureWorks2012AdventureWorks2012 データベース内の SalesReason テーブルを変更します。The following example uses MERGE to modify the SalesReason table in the AdventureWorks2012AdventureWorks2012 database by either updating or inserting rows. ソース テーブルの NewName の値が対象テーブル (SalesReason) の Name 列の値と一致すると、対象テーブルの ReasonType 列が更新されます。When the value of NewName in the source table matches a value in the Name column of the target table, (SalesReason), the ReasonType column is updated in the target table. NewName の値が一致しない場合は、ソース行が対象テーブルに挿入されます。When the value of NewName doesn't match, the source row is inserted into the target table. ソース テーブルは、Transact-SQLTransact-SQL テーブル値コンストラクターを使用して複数の行を指定する派生テーブルです。The source table is a derived table that uses the Transact-SQLTransact-SQL table value constructor to specify multiple rows for the source table. 派生テーブルでテーブル値コンストラクターを使用する方法について詳しくは、「テーブル値コンストラクター (Transact-SQL)」をご覧ください。For more information about using the table value constructor in a derived table, see Table Value Constructor (Transact-SQL). この例では、テーブル変数内の OUTPUT 句の結果を格納する方法も示します。The example also shows how to store the results of the OUTPUT clause in a table variable. さらに、挿入された行と更新された行の数を返す単純な選択操作を実行して、MERGE ステートメントの結果を集計します。And, then you summarize the results of the MERGE statement by running a simple select operation that returns the count of inserted and updated rows.

-- Create a temporary table variable to hold the output actions.  
DECLARE @SummaryOfChanges TABLE(Change VARCHAR(20));  
  
MERGE INTO Sales.SalesReason AS Target  
USING (VALUES ('Recommendation','Other'), ('Review', 'Marketing'),
              ('Internet', 'Promotion'))  
       AS Source (NewName, NewReasonType)  
ON Target.Name = Source.NewName  
WHEN MATCHED THEN  
UPDATE SET ReasonType = Source.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;  

D.D. MERGE ステートメントの結果を別のテーブルに挿入するInserting the results of the MERGE statement into another table

次の例では、MERGE ステートメントの OUTPUT 句から返されたデータをキャプチャし、そのデータを別のテーブルに挿入します。The following example captures data returned from the OUTPUT clause of a MERGE statement and inserts that data into another table. MERGE ステートメントは、Quantity テーブル内で処理される注文に基づいて、AdventureWorks2012AdventureWorks2012 データベース内の ProductInventory テーブルの SalesOrderDetail 列を毎日更新します。The MERGE statement updates the Quantity column of the ProductInventory table in the AdventureWorks2012AdventureWorks2012 database, based on orders that are processed in the SalesOrderDetail table. この例では、更新された行をキャプチャし、在庫変更の追跡に使用する別のテーブルに挿入します。The example captures the updated rows and inserts them into another table that's used to track inventory changes.

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  
            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.E. MERGE を使用して、グラフ データベース内のターゲット エッジ テーブルに対する INSERT または UPDATE を実行するUsing MERGE to do INSERT or UPDATE on a target edge table in a graph database

この例では、ノード テーブル Person および City と、エッジ テーブル livesIn を作成します。In this example, you create node tables Person and City and an edge table livesIn. livesIn エッジに対して MERGE ステートメントを使用し、PersonCity の間にエッジがまだ存在していなければ、新しい行を挿入します。You use the MERGE statement on the livesIn edge and insert a new row if the edge doesn't already exist between a Person and City. エッジが既に存在する場合は、livesIn エッジに対して StreetAddress 属性の更新を行います。If the edge already exists, then you just update the StreetAddress attribute on the livesIn edge.

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

参照See Also