【问题标题】:T SQL merge example needed to help comprehensionT SQL合并示例需要帮助理解
【发布时间】:2012-04-18 21:12:47
【问题描述】:

以下内容:

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 文件中获取的信息。因此,我需要了解如何手动制定查询,以使用这种机制将解析后的数据放入数据库。

【问题讨论】:

  • 我在下面给出了一个演练,但如果我是你,我会在 SO 上发布第二个问题,其中包含你的目标表的结构和来自你的 xml 源的示例 sn-p 并询问.. .我将如何编写一个 MERGE 语句来从这个 xml 更新这个表。还要记住,最后的 MERGE 语句甚至可能不是这项工作的最佳工具。
  • 谢谢,这正是我所需要的。不过,我可能会在稍后提出额外的问题,这是一个很好的建议。

标签: tsql merge


【解决方案1】:

如果您不熟悉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.

【讨论】:

  • FULL JOIN 可以做很棒的事情!
  • 很好的答案,非常彻底。我喜欢总是在 WHEN NOT MATCHED 子句中指定“BY TARGET”或“BY SOURCE”,因为在重新阅读时会更清楚。您不必记住默认值是什么,而且它更接近英语。
【解决方案2】:

在你已经完成的给定答案示例中

DECLARE @Request Int

,但在 SQL 中调用如下:

SELECT @amount, @requestID

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

@amount vs. Amount -> @Amount & Amount

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    • 2011-07-10
    • 1970-01-01
    相关资源
    最近更新 更多