加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

tsql – 在SQL MERGE语句中UPDATE-no-op

发布时间:2020-12-12 16:10:02 所属栏目:MsSql教程 来源:网络整理
导读:我有一个表中有一些持久性的数据.现在当我查询它时,我也有一个很复杂的CTE,计算结果所需的值,我需要将丢失的行插入到持久化表中.最后,我想选择由CTE标识的所有行组成的结果,但是如果表中已经存在表中的数据,并且我需要信息,无论是否插入一行. 简化为这样(如果
我有一个表中有一些持久性的数据.现在当我查询它时,我也有一个很复杂的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预先计算结果,然后执行新的= 0的行的INSERT?我有困难的解释查询计划,因为它基本上归结为一个“集群索引合并”,这是相当模糊的,与单独的SELECT后跟INSERT变体相比,性能明显.而且我不知道SQL Server(具有CU1的2008 R2)是否足够聪明,以便看到UPDATE是无操作的(例如不需要写入).

解决方法

您可以声明一个虚拟变量,并将其值设置在WHEN MATCHED子句中.
DECLARE @dummy int;
 ...
 MERGE
 ...
 WHEN MATCHED THEN
   UPDATE SET @dummy = 0
 ...

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读