【发布时间】:2016-04-30 21:02:43
【问题描述】:
我正在执行一堆 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;
当我去执行这个时,我得到了这个完整的错误
消息 10714,级别 15,状态 1,过程 usp_AdministrationHistoryMerge,第 36 行 “WHEN MATCHED”类型的操作不能在 MERGE 语句的“UPDATE”子句中出现多次。
我查看了 SO 并找到了几种解决此问题的方法,但我发现不适用于此错误的解决方案,而不是删除,我需要将记录的 IsActive 更新为 0。
另外,在我的搜索中,没有人真正解释为什么会抛出这个错误,是的,我知道它很明显,因为错误就在那里,但为什么不允许发生这种情况?基于这种情况,有什么想法可以做到这一点吗?还是当@Action 为0 时我应该让这个合并调用另一个存储过程?
【问题讨论】:
-
您确定要使用
MERGE吗? mssqltips.com/sqlservertip/3074/… -
documentation on MERGE中明确说明:MERGE语句最多可以有两个WHEN MATCHED子句。 * 和 *如果有两个 WHEN MATCHED 子句,那么一个必须指定一个 UPDATE 操作,一个必须指定一个 DELETE 操作。
-
@AaronBertrand,使用 MERGE 不是我的选择,我认为使用 CASE 或 IF 语句会是更好的选择...顺便说一句,文章不错
-
@TT,也许你可以发表你的评论作为答案,如果其他人有同样的问题,而不是 DBA 或通常使用 SQL 的人,可能会受益。
-
@TT.:完全可以在 SQL Server 中使用多个
WHEN MATCHED THEN UPDATE子句来模拟标准 SQLMERGE。只是比较费力。
标签: sql sql-server merge