2016-01-24 115 views
5

我正在做一堆CRUD操作并创建CUD合并storedprocs。我的存储过程是这样的为什么WHEN MATCHED'不能在MERGE语句的'UPDATE'子句中出现多次?

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; 

当我去执行这个我得到这个完整的错误

消息10714,级别15,状态1,过程usp_AdministrationHistoryMerge,36号线 类型的动作'WHEN MATCHED'不能在MERGE语句的'UPDATE'子句中出现多次。

我环顾四周,发现了一些方法来解决这个问题,但是我发现这个错误并不适合解决这个问题,而不是删除,我需要将记录的IsActive更新为0.

此外,在我的搜索没有人真正解释为什么这个错误被抛出,是的,我知道它很明显,因为错误是在那里,但为什么这是不允许发生?基于这种情况,有没有关于如何做到这一点的想法?或者当@Action为0时,我应该有这个合并调用另一个storedproc?

+0

您是否确信要使用MERGE? https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ –

+3

它在[MERGE文档](https://msdn.microsoft.com /en-us/library/bb510625.aspx):* MERGE语句最多可以有两个WHEN MATCHED子句。 * **和** *如果有两个WHEN MATCHED子句,则必须指定一个UPDATE动作,并且必须指定一个DELETE动作。* –

+0

@AaronBertrand,使用MERGE不是我的选择,我使用CASE或IF语句的数字会是更好的选择......好的文章的方式 – Chris

回答

5

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

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

但是,这是不允许的。它在Documentation on MERGE明确提出:

MERGE语句可以有最多两个WHEN MATCHED条款。

而且

如果有两个WHEN MATCHED条款,则必须指定一个UPDATE动作和一个必须指定DELETE行动。

而且重要的是要知道的是:

如果UPDATE在<指定merge_matched >条款,以及超过<table_source>的一排target_table基于<merge_search_condition>,SQL相匹配的行服务器返回一个错误。 MERGE语句不能多次更新同一行,或者更新和删除同一行。