为什么WHEN MATCHED'在MERGE语句的'UPDATE'子句中不能出现多次?

时间:2016-01-24 15:31:20

标签: sql sql-server merge

我正在接受一堆CRUD操作并从CUD创建合并存储过程。我的存储过程看起来像这样

CREATE PROCEDURE usp_AdministrationHistoryMerge
    @AdministrationHistoryID int out,
    @AdministratorID int,
    @DateCreated datetime,
    @CreatedBy nvarchar(50),
    @ModifiedBy nvarchar(50),
    @Action int
AS

SET NOCOUNT OFF
SET TRANSACTION ISOLATION LEVEL READ COMMITTED

DECLARE @ERROR_SEVERITY int,
        @MESSAGE varchar(1000),
        @ERROR_NUMBER int,
        @ERROR_PROCEDURE nvarchar(200),
        @ERROR_LINE int,
        @ERROR_MESSAGE nvarchar(4000),
        @IsActive bit,
        @DateModified datetime;
begin try
    if @Action = 1
        begin
            set @IsActive = 1
            set @AdministrationHistoryID = SCOPE_IDENTITY()
        end
    merge [AdministrationHistory] as target
    using (select @AdministratorID, @DateCreated, @CreatedBy, @DateModified, @ModifiedBy, @IsActive)
    as source (AdministratorID, DateCreated, CreatedBy, DateModified, ModifiedBy, IsActive)
    on (target.AdministrationHistoryID = source.AdministrationHistoryID)
    when matched and @Action = -1 then
        update
            set IsActive = 0
    when matched and @Action = 0 then
        update
        set ModifiedBy = @ModifiedBy,
        DateModified = GETDATE()
    when matched and @Action = 1 then
    insert
    (AdministratorID, DateCreated, CreatedBy, IsActive)
    values
    (@AdministratorID, @DateCreated, @CreatedBy, @IsActive);
end try

BEGIN CATCH
    SET @ERROR_SEVERITY = ISNULL(ERROR_SEVERITY(),'');
    SET @ERROR_NUMBER = ISNULL(ERROR_NUMBER(),'');
    SET @ERROR_PROCEDURE = ISNULL(ERROR_PROCEDURE(),''); 
    SET @ERROR_LINE = ISNULL(ERROR_LINE(),'');
    SET @ERROR_MESSAGE = ISNULL(ERROR_MESSAGE(),'');

    -- Test if the transaction is uncommittable.
    IF (XACT_STATE()) = -1
        BEGIN
            --PRINT N'The transaction is in an uncommittable state. Rolling back transaction.'
            ROLLBACK TRANSACTION;
        END;

    -- Test if the transaction is active and valid.
    IF (XACT_STATE()) = 1
        BEGIN
            --PRINT N'The transaction is committable. Committing transaction.'
            COMMIT TRANSACTION;   
        END;

    SET @MESSAGE = 'Error Occured in Stored Procedure ' + cast(@ERROR_PROCEDURE as varchar(200)) + 
                    '; Line Number ' + cast(@ERROR_LINE as varchar) + 
                    '; Message: [' + cast(@ERROR_NUMBER as varchar) + '] - '
                    + cast(@ERROR_MESSAGE as varchar(255))

    RAISERROR(@MESSAGE, @ERROR_SEVERITY, 1);
END CATCH;

当我执行此操作时,我收到此完整错误

  

Msg 10714,Level 15,State 1,Procedure usp_AdministrationHistoryMerge,Line 36   “WHEN MATCHED”类型的操作在MERGE语句的“UPDATE”子句中不能出现多次。

我已经查看了SO并找到了几种方法来解决这个问题,但是我发现这个错误的解决方案并不合适,因为我不需要删除而需要将记录的IsActive更新为0。 / p>

此外,在我的搜索中,没有人真正解释为什么会抛出这个错误,是的,我知道它很明显,因为错误就在那里,但为什么不允许这样做呢?基于这种情况,有什么想法如何实现这一点?或者我应该在@Act​​ion为0时将此合并调用另一个storedproc?

2 个答案:

答案 0 :(得分:8)

MERGE声明中,您有三个WHEN MATCHED条款

  • 两个UPDATE声明
  • 一个INSERT声明。

然而,这是不允许的。 Documentation on MERGE

中明确说明了这一点
  

MERGE语句最多可包含两个WHEN MATCHED条款。

并且

  

如果有两个WHEN MATCHED子句,则必须指定UPDATE个动作,并且必须指定DELETE个动作。

同样重要的是要知道:

  

如果在< merge_matched>中指定UPDATE子句,以及< table_source>的多行基于< merge_search_condition>匹配target_table中的行,SQL Server返回错误。 MERGE语句不能多次更新同一行,也不能更新和删除同一行。

答案 1 :(得分:0)

SQL标准(例如Db2)允许这样做,但SQL Server不允许。 This article documents how you can emulate several WHEN MATCHED THEN UPDATE clauses also in SQL Server。就您而言

print("not"+"X")