Zajmuję się wieloma opcjami typu CRUD i tworzeniem scalonych przechowywanych plików z CUD. My przechowywane proc wygląda toDlaczego WHEN MATCHED "nie może pojawić się więcej niż jeden raz w klauzuli" UPDATE "instrukcji MERGE?
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;
Kiedy idę do wykonania tego otrzymuję ten Full Error
Msg 10714, Level 15, State 1, Procedura usp_AdministrationHistoryMerge, Linia 36 Działanie typu "WHEN MATCHED" nie może pojawić się więcej niż jeden raz w klauzuli "UPDATE" instrukcji MERGE.
Rozejrzałem się po SO i znalazłem kilka sposobów rozwiązania tego problemu, ale to, co znalazłem, nie jest odpowiednim rozwiązaniem dla tego błędu, ponieważ zamiast usuwania i muszę zaktualizować IsActive rekordu do 0.
Ponadto, w moich poszukiwań nikt tak naprawdę nie wyjaśnia, dlaczego ten błąd jest rzucany, tak, wiem, że jest to oczywiste, ponieważ błąd jest właśnie tutaj, ale dlaczego nie jest to dozwolone? i na tej podstawie są jakieś pomysły, jak to osiągnąć? lub powinienem mieć to połączenie połączyć inny storedproc, gdy @Action jest 0?
Czy jesteś przekonany, że chcesz użyć "MERGE"? https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ –
Jest to wyraźnie określone w [dokumentacji MERGE] (https://msdn.microsoft.com /en-us/library/bb510625.aspx): * Instrukcja MERGE może zawierać co najwyżej dwie klauzule WHEN MATCHED. * ** i ** * Jeśli istnieją dwie klauzule WHEN MATCHED, należy określić akcję UPDATE, a należy określić akcję DELETE.* –
@AaronBertrand, To nie był mój wybór, aby użyć MERGE, myślę, że użycie CASE lub instrukcji IF byłoby lepszym wyborem ... Przyjemny artykuł przy okazji – Chris