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

Joh*_*0te 39 t-sql 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);
Run Code Online (Sandbox Code Playgroud)

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

有人可以请:

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

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

RTh*_*mas 75

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

因此,使用提供的代码示例可以查看表Commissionions_history

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  12.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |
Run Code Online (Sandbox Code Playgroud)

merge语句在一个名为"target"的表和一个表达式之间创建一个完整的连接,该表返回一个名为"source"的表(或逻辑上非常类似于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)   
Run Code Online (Sandbox Code Playgroud)

当被认为是连接时,创建以下结果集.

|  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        |
Run Code Online (Sandbox Code Playgroud)

在发现匹配的条件下,使用给出的有关如何对目标执行操作的说明.

WHEN MATCHED THEN        
UPDATE SET amount = source.amount    
Run Code Online (Sandbox Code Playgroud)

生成的目标表现在看起来像这样.具有请求1234的行被更新为18.

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  18.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |
Run Code Online (Sandbox Code Playgroud)

由于匹配WAS发现没有其他事情发生.但是让我们说源的值是这样的.

DECLARE @Amount Decimal = 18.00;
DECLARE @Request Int = 1239;
Run Code Online (Sandbox Code Playgroud)

生成的连接看起来像这样:

|  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        |
Run Code Online (Sandbox Code Playgroud)

由于在目标中找不到匹配的行,因此该语句执行另一个子句.

WHEN NOT MATCHED THEN                                 
INSERT (request, amount)                                 
VALUES (source.request, source.amount);  
Run Code Online (Sandbox Code Playgroud)

导致目标表现在看起来像这样:

|  Amount  |   Request  |   <other fields> |
--------------------------------------------
|  12.00   |   1234     |   <other data>   |
|  14.00   |   1235     |   <other data>   |
|  15.00   |   1236     |   <other data>   |
|  18.00   |   1239     |   <other data>   |
Run Code Online (Sandbox Code Playgroud)

合并语句的真正潜力是源和目标都是大表.因为它可以使用单个简单语句为每行执行大量更新和/或插入.

最后一点.重要的是要记住not matched默认为完整子句not matched by target,但是您可以指定not matched by source默认子句的替代或补充.merge语句支持两种类型的不匹配(源中的记录不在目标中,或者目标中的记录不在on子句中定义的). 您可以在MSDN上找到完整的文档,限制和完整语法.