如果您不熟悉join 语句,那么这就是您需要开始的地方。了解连接的工作原理是其余部分的关键。一旦您熟悉了联接,那么通过将其视为完全联接以及如何处理匹配或不匹配的行的说明,理解合并是最容易的。
因此,使用提供的代码示例让我们看一下 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 子句定义)。 您可以在 MSDN 上找到完整的文档、限制和完整的语法。