SQL Merge语句中的更新-NO-OP
-
24-10-2019 - |
题
我有一个具有一些持久数据的表。现在,当我查询它时,我还拥有一个非常复杂的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
然后执行 INSERT
行是 new=0
?我很难解释查询计划,因为它基本上归结为“群集索引合并”,这对我而言,与单独的性能相比,这对我来说很模糊 SELECT
其次是 INSERT
变体。我想知道SQL Server(2008 r2带有CU1)是否真的足够聪明,可以看到 UPDATE
是一个no-op(例如不需要写)。
解决方案
您可以声明一个虚拟变量,并在匹配的子句中设置其值。
DECLARE @dummy int;
...
MERGE
...
WHEN MATCHED THEN
UPDATE SET @dummy = 0
...
我相信它应该比实际的表更新便宜。
不隶属于 StackOverflow