如果您不熟悉join statements,那么您需要从那里开始。了解连接的工作原理是其余部分的关键。一旦您熟悉了联接,那么通过将合并视为完全联接以及对匹配或不匹配的行执行什么操作的说明,最容易理解合并。
因此,使用提供的代码示例,让我们看看 Commissions_history 表
| Amount | Request | <other fields> |
--------------------------------------------
| 12.00 | 1234 | <other data> |
| 14.00 | 1235 | <other data> |
| 15.00 | 1236 | <other data> |
合并语句在称为“目标”的表和返回称为“源”的表(或在逻辑上与 CTE 等表非常相似的结果集)的表达式之间创建完全连接。
在给出的示例中,它使用变量作为源,我们假设已由用户设置或作为参数传递。
DECLARE @Amount Decimal = 18.00;
DECLARE @Request Int = 1234;
MERGE dbo.commissions_history AS target
USING (SELECT @amount, @requestID) AS source (amount, request)
ON (target.request = source.request)
在将其视为联接时创建以下结果集。
| Amount | Request | <other fields> | Source.Amount | Source.Request |
------------------------------------------------------------------------------
| 12.00 | 1234 | <other data> | 18.00 | 1234 |
| 14.00 | 1235 | <other data> | null | null |
| 15.00 | 1236 | <other data> | null | null |
在找到匹配项的情况下,使用给出的关于对目标执行什么操作的说明。
WHEN MATCHED THEN
UPDATE SET amount = source.amount
生成的目标表现在看起来像这样。请求 1234 的行更新为 18。
| Amount | Request | <other fields> |
--------------------------------------------
| 18.00 | 1234 | <other data> |
| 14.00 | 1235 | <other data> |
| 15.00 | 1236 | <other data> |
自从发现匹配后,没有其他任何事情发生。但是可以说源头的值是这样的。
DECLARE @Amount Decimal = 18.00;
DECLARE @Request Int = 1239;
生成的连接如下所示:
| Amount | Request | <other fields> | Source.Amount | Source.Request |
------------------------------------------------------------------------------
| 12.00 | 1234 | <other data> | null | null |
| 14.00 | 1235 | <other data> | null | null |
| 15.00 | 1236 | <other data> | null | null |
| null | null | null | 18.00 | 1239 |
由于在目标中未找到匹配的行,因此语句执行另一个子句。
WHEN NOT MATCHED THEN
INSERT (request, amount)
VALUES (source.request, source.amount);
导致现在看起来像这样的目标表:
| Amount | Request | <other fields> |
--------------------------------------------
| 12.00 | 1234 | <other data> |
| 14.00 | 1235 | <other data> |
| 15.00 | 1236 | <other data> |
| 18.00 | 1239 | <other data> |
合并语句真正的潜力在于源和目标都是大表。因为它可以通过一个简单的语句对每一行进行大量更新和/或插入。
最后一点。重要的是要记住 not matched 默认为完整子句 not matched by target,但是您可以指定 not matched by source 来代替默认子句,或者作为默认子句的补充。合并语句支持两种类型的不匹配(源中的记录不在目标中,或者目标中的记录不在源中由 on 子句定义)。 You can find full documentation, restrictions, and complete syntax on MSDN.