使用cte UPDATE SET <multiple>失败,单个UPDATE SET工作

时间:2017-02-03 22:22:57

标签: sql-server sql-update common-table-expression

对不起,这是一个更长的。我把代码完成了。

真实代码涉及详细报告的数据桶。我的cte块失败了。另一种方法是编写一个SET的一些UPDATE块和一个连接 - 丑陋但有效。

在给定的cte块中,无论我把它放在cte块中的什么地方,我都只能填充Hair。在更低的UPDATE块中,一切都运行良好。 (在我的实际情况中,我的cte join有大约140k记录,每次更新都会返回一个随机数量的记录:/)

我这次犯了什么愚蠢的错误?

谢谢, 蒂斯

IF OBJECT_ID('tempdb..#TempList') IS NOT NULL
    DROP TABLE #TempList
IF OBJECT_ID('tempdb..#TempValues') IS NOT NULL
    DROP TABLE #TempValues

CREATE TABLE #TempList (
    Name NVARCHAR(20),
    Hair NVARCHAR(20),
    Height NVARCHAR(20),
    Job NVARCHAR(20)
)
CREATE TABLE #TempValues (
    Name NVARCHAR(20),
    VariableName NVARCHAR(20) ,
    VariableValue NVARCHAR(20)
)
INSERT INTO #TempList
        ( Name ,
          Hair ,
          Height,
          Job
        )
VALUES
    ('Fred', NULL, NULL, NULL),
    ('Wilma', NULL, NULL, NULL),
    ('Barney', NULL, NULL, NULL),
    ('Betty', NULL, NULL, NULL),
    ('Pebbles', NULL, NULL, NULL),
    ('Bammbamm', NULL, NULL, NULL)

INSERT INTO #TempValues
        ( Name ,
          VariableName ,
          VariableValue
        )
VALUES
    ('Fred', 'Hair','Dark'),
    ('Fred', 'Height','6-1'),
    ('Fred', 'Weight','220'),
    ('Wilma', 'Hair','Red'),
    ('Wilma', 'Height','5-5'),
    ('Wilma', 'Weight','125'),
    ('Barney', 'Hair','Blond'),
    ('Barney', 'Weight','195'),
    ('Barney', 'Job','Worker'),
    ('Barney', 'Married','Yes'),
    ('Betty', 'Hair','Dark'),
    ('Betty', 'Height','5-3'),
    ('Pebbles', 'Hair','Red')

;WITH cte_name AS (
     SELECT TL.Name ,
            TL.Hair ,
            TL.Height ,
            TL.Job ,
            TV.VariableName ,
            TV.VariableValue
        FROM #TempList TL
            JOIN #TempValues TV ON TV.Name = TL.Name
     )
UPDATE cte_name 
    SET 
        cte_name.Height = 
            CASE  cte_name.VariableName
                WHEN 'Height' THEN cte_name.VariableValue
            END ,   
        cte_name.Hair = 
            CASE  cte_name.VariableName
                WHEN 'Hair' THEN cte_name.VariableValue
            END ,
        cte_name.Job = 
            CASE  cte_name.VariableName
                WHEN 'Job' THEN cte_name.VariableValue
            END

SELECT * FROM #TempList
SELECT * FROM #TempValues

--UPDATE #TempList SET Hair = NULL , Height = NULL , Job = NULL

-- Run either the top UPDATE or these updates
UPDATE #TempList
    SET Height = TV.VariableValue
        FROM #TempList TL
            JOIN #TempValues TV ON TV.Name = TL.Name
        WHERE TV.VariableName = 'Height'
UPDATE #TempList
    SET Hair = TV.VariableValue
        FROM #TempList TL
            JOIN #TempValues TV ON TV.Name = TL.Name
        WHERE TV.VariableName = 'Hair'
UPDATE #TempList
    SET Job = TV.VariableValue
        FROM #TempList TL
            JOIN #TempValues TV ON TV.Name = TL.Name
        WHERE TV.VariableName = 'Job'

1 个答案:

答案 0 :(得分:1)

这将使其工作,完全替换现有的cte与下面的一个:

;
with cte as (            
    select Name,[Hair],[Height],[Job] from #TempValues tv
    pivot (min(VariableValue) for VariableName in ([Hair],[Height],[Job]) ) pvt
) 
UPDATE t
SET    
        t.Height = ISNULL(cte.Height, t.Height),            
        t.Hair = ISNULL(cte.Hair, t.Hair),
        t.Job = ISNULL(cte.Job, t.Job)            
from #TempList t
join cte on cte.Name = t.Name

对您的数据运行上述查询后,select * from #TempValues会生成以下输出(我还在ID int not null identity(1,1)表中添加了#TempList):

enter image description here

说明:

首先,我们使用PIVOT将垂直属性/值转换为水平列,因此select * from cte会产生以下结果:

enter image description here

然后我们使用ISNULL(...)过滤掉UPDATE调用中的NULL值。

如果您还需要权重列,只需在[Job]子句和{更新部分}中的pivot(...)之后添加。

希望这有帮助。

PS。 2/15/2017添加此非工作UPDATE版本以供参考:

UPDATE t
SET    
    t.Height = 
        CASE  tv.VariableName
            WHEN 'Height' THEN tv.VariableValue
        END ,   
    t.Hair = 
        CASE  tv.VariableName
            WHEN 'Hair' THEN tv.VariableValue
        END ,
    t.Job = 
        CASE  tv.VariableName
            WHEN 'Job' THEN tv.VariableValue
        END
FROM #TempList t
JOIN #TempValues TV ON TV.Name = t.Name

注意,这是没有CTE的直接UPDATE,如果我删除#TempValues JOIN并将JOIN添加到CTE,结果是相同的:它只更新每个Name的第一个属性。如果您在每个名称的INSERT ... VALUES (...)列表中切换头发和高度,则将更新高度而不是头发。

我还没发现它为什么会这样。如果我找到了什么,我会在这里发帖。

相关问题