tsql - SQL MERGE语句中的UPDATE-no-op

标签 tsql sql-server-2008 sql-update sql-merge

我有一个包含一些持久性数据的表。现在,当我查询它时,我还有一个相当复杂的CTE,它计算结果所需的值,并且需要在持久表中插入缺少的行。最后,我想选择一个结果,该结果由CTE标识的所有行组成,但要包含表中的数据(如果它们已在表中),并且我需要有关是否已插入行的信息。

简化后的工作方式如下(如果您想尝试,以下代码将作为普通查询运行):

-- Set-up of test data, this would be the persisted table 
DECLARE @target TABLE (id int NOT NULL PRIMARY KEY) ;
INSERT INTO @target (id) SELECT v.id FROM (VALUES (1), (2)) v(id);

-- START OF THE CODE IN QUESTION
-- The result table variable (will be several columns in the end)
DECLARE @result TABLE (id int NOT NULL, new bit NOT NULL) ;

WITH Source AS (
    -- Imagine a fairly expensive, recursive CTE here
    SELECT * FROM (VALUES (1), (3)) AS Source (id)
)
MERGE INTO @target AS Target
    USING Source
    ON Target.id = Source.id
    -- Perform a no-op on the match to get the output record
    WHEN MATCHED THEN 
        UPDATE SET Target.id=Target.id
    WHEN NOT MATCHED BY TARGET THEN
        INSERT (id) VALUES (SOURCE.id)
    -- select the data to be returned - will be more columns
    OUTPUT source.id, CASE WHEN $action='INSERT' THEN CONVERT(bit, 1) ELSE CONVERT(bit, 0) END
      INTO @result ;

-- Select the result
SELECT * FROM @result;

我不喜欢WHEN MATCHED THEN UPDATE部分,我宁愿将多余的更新保留下来,但随后在OUTPUT子句中没有得到结果行。

这是完成此类数据并返回数据的最有效方法吗?

还是有没有MERGE的更有效的解决方案,例如通过使用SELECT预先计算结果,然后对INSERT的行执行new=0呢?我很难解释查询计划,因为它基本上可以归结为“集群索引合并”,与单独的SELECTINSERT变体相比,这对我来说在性能方面非常模糊。而且我想知道SQL Server(带有CU1的2008 R2)是否真的足够聪明,以至于UPDATE是无操作的(例如,无需写操作)。

最佳答案

您可以声明一个虚拟变量,并在WHEN MATCHED子句中设置其值。

 DECLARE @dummy int;
 ...
 MERGE
 ...
 WHEN MATCHED THEN
   UPDATE SET @dummy = 0
 ...

我相信它应该比实际的表更新便宜。

关于tsql - SQL MERGE语句中的UPDATE-no-op,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5316669/

相关文章:

asp.net - 从 Web 调用时存储过程较慢,从 Management Studio 调用时较快

sql - 在 SELECT INTO 语句中添加额外的列

mysql - Varchar类型和性能问题

sql - 如何使用 GROUP BY 在 T-SQL 中返回同一行的多个列

c# - 在 SQL Server 的 .NET/Entity Framework 中设置事务隔离级别

sql - 如何获取 SQL Server 2008 月份的最后一个日期

sql-server-2008 - sql server删除列重建索引吗?

mysql - 如何多次更新表上的字段,不包括不存在的字段

mysql - 使用 join 和 max 更新行

sql - 如何更新 sql server 中的前 100 条记录