在SQL Server中使用MERGE插入不起作用

时间:2016-05-25 11:15:27

标签: sql-server merge

我有一个带有以下查询的存储过程在SQL Server中使用MERGE插入/更新,但查询可以正常进行更新,但它不适用于Insert。 虽然我在Target中获得了正确的更新记录但是对于新插入,它失败了。 基本上,我有4个表.SUPPORT_STAFF_BAK是需要从源表UNIQUE_DUP_TEST更新的目标表,基于来自我尝试使用连接实现的其他两个表(REF_FUNCTION,DATA_PERIOD)的几个条件。 根据条件,我们需要检查目标,如果当前data_period存在相同的ggid,我们需要更新它,否则我们需要根据条件再次插入新记录。

    MERGE SUPPORT_STAFF_BAK AS SUPP_STAFF
USING 
(SELECT G_UNIQUE.[GLOBAL_ID],

G_UNIQUE.[FIRST_NAME],
G_UNIQUE.[LAST_NAME],
G_UNIQUE.[EMAIL],
G_UNIQUE.[Gender],
G_UNIQUE.[DATE_OF_BIRTH],
G_UNIQUE.[PRODUCTION_UNIT_CODE],
ORG.[LEGAL_ENTITY_COUNTRY_CODE],
ORG.[LEGAL_ENTITY_COUNTRY],
G_UNIQUE.[JOB_NAME],
ORG.[BU_CODE],
ORG.[BU_NAME],
ORG.[SBU_CODE],
ORG.[SBU_NAME],
G_UNIQUE.[GRADE_LETTER],
CASE 
WHEN G_UNIQUE.[EMPLOYEE_STATUS] = 'A' THEN 'Active'
WHEN G_UNIQUE.[EMPLOYEE_STATUS] = 'S' THEN 'Suspended'
WHEN G_UNIQUE.[EMPLOYEE_STATUS]= 'T' THEN 'Terminated' 
END AS [EMPLOYEE_STATUS],
CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE '' 
END AS [CATEGORY],
G_UNIQUE.[CATEGORY_DETAIL],
G_UNIQUE.[FIRST_JOINING_DATE],
PERIOD.DATA_PERIOD_ID
FROM    UNIQUE_DUP_TEST  G_UNIQUE 
INNER JOIN GDH_ORG ORG
ON G_UNIQUE.PRODUCTION_UNIT_CODE=ORG.PRODUCTION_UNIT_CODE
INNER JOIN REF_FUNCTION FUNC 
ON G_UNIQUE.CATEGORY_DETAIL=FUNC.FUNCTION_CODE 
INNER JOIN DATA_PERIOD PERIOD 
ON FUNC.FUNCTION_ID=PERIOD.FUNCTION_ID 
WHERE  PERIOD.DATA_YEAR=YEAR(GETDATE()) AND PERIOD.DATA_MONTH=MONTH(GETDATE())
) AS G_SOURCE
ON SUPP_STAFF.GGID = G_SOURCE.GLOBAL_ID AND SUPP_STAFF.PRODUCTION_UNIT_CODE=G_SOURCE.PRODUCTION_UNIT_CODE           
    AND SUPP_STAFF.DATA_PERIOD_ID=G_SOURCE.DATA_PERIOD_ID
WHEN MATCHED  THEN 

UPDATE SET 
[SUPP_STAFF].[FIRST_NAME]       = G_SOURCE.[FIRST_NAME],
[SUPP_STAFF].[LAST_NAME]        = G_SOURCE.[LAST_NAME],
[SUPP_STAFF].[EMAIL]            = G_SOURCE.[EMAIL],
[SUPP_STAFF].[GENDER]           = G_SOURCE.[Gender],
[SUPP_STAFF].[DATE_OF_BIRTH]    = G_SOURCE.[DATE_OF_BIRTH],
[SUPP_STAFF].[LEGAL_ENTITY_COUNTRY_CODE] = G_SOURCE.[LEGAL_ENTITY_COUNTRY_CODE],
[SUPP_STAFF].[LEGAL_ENTITY_COUNTRY_NAME] = G_SOURCE.[LEGAL_ENTITY_COUNTRY],
[SUPP_STAFF].[GCM_ROLE]         = G_SOURCE.[JOB_NAME],
[SUPP_STAFF].[BU_CODE]          = G_SOURCE.[BU_CODE],
[SUPP_STAFF].[BU_NAME]          = G_SOURCE.[BU_NAME],
[SUPP_STAFF].[SBU_CODE]         = G_SOURCE.[SBU_CODE],
[SUPP_STAFF].[SBU_NAME]         = G_SOURCE.[SBU_NAME],
[SUPP_STAFF].[GRADE]            = G_SOURCE.[GRADE_LETTER],
[SUPP_STAFF].[EMPLOYEE_STATUS]  = G_SOURCE.[EMPLOYEE_STATUS],
[SUPP_STAFF].[EMPLOYEE_CATEGORY] = G_SOURCE.[CATEGORY],
[SUPP_STAFF].[START_DATE]       = G_SOURCE.[FIRST_JOINING_DATE],
[SUPP_STAFF].[UPDATE_DATE]      = GETDATE(),
[SUPP_STAFF].[UPDATE_USER]      = CASE  WHEN G_SOURCE.[EMPLOYEE_STATUS]='Terminated' THEN 'Delete'
                                        WHEN G_SOURCE.[EMPLOYEE_STATUS]<>'Terminated' THEN 'Update' 
                                    END,
[SUPP_STAFF].[SUPPORT_STAFF_FUNCTION]   =   CASE    WHEN G_SOURCE.[EMPLOYEE_STATUS]='Terminated' THEN NULL
                                                    WHEN G_SOURCE.[EMPLOYEE_STATUS]<>'Terminated' THEN G_SOURCE.[CATEGORY_DETAIL]
                                            END

WHEN NOT MATCHED  AND G_SOURCE.[CATEGORY] = 'CC1' 
                    AND G_SOURCE.[EMPLOYEE_STATUS] IN ('A, S') 
THEN
INSERT(         [GGID],
                [FIRST_NAME],               
                [LAST_NAME],                
                [EMAIL],                    
                [GENDER],                   
                [DATE_OF_BIRTH],            
                [LEGAL_ENTITY_COUNTRY_CODE],
                [LEGAL_ENTITY_COUNTRY_NAME],
                [GCM_ROLE],                 
                [BU_CODE],                  
                [BU_NAME],                  
                [SBU_CODE],                 
                [SBU_NAME],                 
                [GRADE],                    
                [EMPLOYEE_STATUS],          
                [EMPLOYEE_CATEGORY],        
                [START_DATE],               
                [UPDATE_DATE],              
                [UPDATE_USER],
                [SUPPORT_STAFF_FUNCTION]    
)
VALUES (     
                G_SOURCE.[GLOBAL_ID],
                G_SOURCE.[FIRST_NAME],  
                G_SOURCE.[LAST_NAME],
                G_SOURCE.[EMAIL],
                G_SOURCE.[Gender],
                G_SOURCE.[DATE_OF_BIRTH],
                G_SOURCE.[LEGAL_ENTITY_COUNTRY_CODE],
                G_SOURCE.[LEGAL_ENTITY_COUNTRY],
                G_SOURCE.[JOB_NAME],
                G_SOURCE.[BU_CODE],
                G_SOURCE.[BU_NAME],
                G_SOURCE.[SBU_CODE],
                G_SOURCE.[SBU_NAME],
                G_SOURCE.[GRADE_LETTER],
                G_SOURCE.[EMPLOYEE_STATUS],
                G_SOURCE.[CATEGORY_DETAIL],
                G_SOURCE.[FIRST_JOINING_DATE],
                GETDATE(),
                'Insert',
                G_SOURCE.[CATEGORY_DETAIL]

        )

OUTPUT $action,

INSERTED.GGID作为GGID; SELECT @@ ROWCOUNT;

2 个答案:

答案 0 :(得分:0)

你的一个假设是错误的。源查询的行数少于您的想法,或者存在匹配项,或者不满足插入条件。否则查询就可以了。

要调试这个,我会将源查询插入临时表并手动检查其内容,以确保它们符合您的期望。

然后,您可以加入目标,看看您的插入内容是否可以转换为更新(例如select * from Source join Target on ...)。在内部,MERGE只是一个完整的外连接,你可以手动重现。

现在没人能告诉你确切的答案。您需要自己调试并检查数据。

答案 1 :(得分:0)

最后我发现了错误。错误发生在以下2个地方 -

CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE '' END AS [CATEGORY],

我用

替换了它
CASE WHEN G_UNIQUE.[CATEGORY] = 'DSS' THEN G_UNIQUE.[CATEGORY_DETAIL] ELSE '' 
END AS [EMPLOYEE_FUNCTION],

此外,我在Source查询中又添加了一个列 -

G_UNIQUE.[CATEGORY],

此外,下面有错误的代码

WHEN NOT MATCHED  AND G_SOURCE.[CATEGORY] = 'CC1' 
                AND G_SOURCE.[EMPLOYEE_STATUS] IN ('A, S')

被以下正确的代码替换 -

    WHEN NOT MATCHED  AND G_SOURCE.[CATEGORY] = 'CC1' 
                    AND G_SOURCE.[EMPLOYEE_STATUS] IN ('Active', 'Suspended')

实际上,我缺少1个源列,并且在插入时检查了相同的值,因此插入失败了。 此外,在Employee_status的源代码中,我将值检查为A,S和T,然后将它们替换为Active,Suspended,Terminated但在插入时不匹配时,我每次都检查A,S,T的值返回错误,因此插入失败。