T SQL合并示例需要帮助理解

时间:2012-04-18 21:12:47

标签: tsql merge

以下内容:

MERGE dbo.commissions_history AS target
USING (SELECT @amount, @requestID) AS source (amount, request)
ON (target.request = source.request)
WHEN MATCHED THEN
    UPDATE SET amount = source.amount
WHEN NOT MATCHED THEN
    INSERT (request, amount)
    VALUES (source.request, source.amount);
来自https://stackoverflow.com/a/2967983/857994

是一种非常好的插入/更新方式(并删除了一些额外的工作)。即使经过一些谷歌搜索,我发现很难遵循。

有人可以:

  • 用简单的术语解释一下 - 在这种情况下,MSDN文档毁了我的大脑。
  • 告诉我如何修改它以便用户可以输入金额和值的值。请求而不是从其他数据库位置选择它们?

基本上,我想使用它从C#应用程序插入/更新,其中包含从我正在获取的XML文件中获取的信息。因此,我需要了解如何手动制定查询以使用此机制将解析后的数据导入数据库。

2 个答案:

答案 0 :(得分:74)

如果您不熟悉join statements那么那就是您需要开始的地方。了解联接如何工作是其余的关键。一旦熟悉了连接,那么通过将其视为一个完整的连接来理解合并是最简单的,其中包含有关对哪些行进行匹配或不匹配的说明。

因此,使用提供的代码示例,请查看表commissions_history

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  12.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |

merge语句在一个名为“target”的表和一个表达式之间创建一个完整的连接,该表返回一个名为“source”的表(或逻辑上非常类似于CTE的表的结果集)。 / p>

在给出的示例中,它使用变量作为源,我们假设它们已由用户设置或作为参数传递。

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

由于比赛WAS发现没有其他事情发生。但是,让我们说源的值是这样的。

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来代替默认子句,或者除了默认子句之外还指定{{1}}。 merge语句支持两种类型的不匹配(源中的记录不在目标中,或者目标中的记录不在源中,由on子句定义)。 You can find full documentation, restrictions, and complete syntax on MSDN.

答案 1 :(得分:0)

在给出的答案示例中,您已完成

DECLARE @Request Int

,但在SQL中调用它如下:

SELECT @amount, @requestID

另一个是以相同的方式命名和调用变量:

@amount vs. Amount -> @Amount & Amount