Preciso executar um UPDATE e um INSERT em uma única transação. Esse código funciona bem por si só, mas eu gostaria de poder chamá-lo facilmente e passar os parâmetros necessários. Quando tento aninhar esta transação em um procedimento armazenado, encontro muitos erros de sintaxe.
Como posso encapsular o código a seguir para que ele possa ser chamado facilmente?
BEGIN TRANSACTION AssignUserToTicket
GO
DECLARE @updateAuthor varchar(100)
DECLARE @assignedUser varchar(100)
DECLARE @ticketID bigint
SET @updateAuthor = 'user1'
SET @assignedUser = 'user2'
SET @ticketID = 123456
UPDATE tblTicket SET ticketAssignedUserSamAccountName = @assignedUser WHERE (ticketID = @ticketID);
INSERT INTO [dbo].[tblTicketUpdate]
([ticketID]
,[updateDetail]
,[updateDateTime]
,[userSamAccountName]
,[activity])
VALUES
(@ticketID,
'Assigned ticket to ' + @assignedUser,
GetDate(),
@updateAuthor,
'Assign');
GO
COMMIT TRANSACTION AssignUserToTicket
Respostas:
Você precisa envolver esse código na
CREATE PROCEDURE ...
sintaxe e remover asGO
instruçõesBEGIN TRANSACTION
antes e depoisCOMMIT TRANSACTION
.Observe também que adicionei um
TRY...CATCH
bloco de instrução para permitir a execução de umaROLLBACK TRANSACTION
instrução caso ocorra algum erro. Você provavelmente precisa de um tratamento de erros melhor que isso, mas sem o conhecimento de seus requisitos, isso é difícil na melhor das hipóteses.Boa leitura:
Sempre especifique o esquema
Práticas recomendadas para procedimentos armazenados
Maus hábitos a evitar
fonte
SAVE TRANS
implicações do comando.Se você deseja manipular adequadamente os procedimentos armazenados aninhados que podem manipular transações (iniciadas no T-SQL ou no código do aplicativo), siga o modelo que descrevi na resposta a seguir:
Somos obrigados a manipular transações no código C #, bem como no procedimento armazenado
Você notará duas diferenças no que está tentando aqui:
O uso de
RAISERROR
dentro doCATCH
bloco. Isso corrige o erro até o nível de chamada (seja na camada de banco de dados ou de aplicativo), para que uma decisão possa ser tomada com relação ao fato de que ocorreu um erro.Não
SAVE TRANSACTION
. Eu nunca encontrei um caso para usar isso. Sei que algumas pessoas preferem isso, mas em tudo o que já fiz em qualquer lugar em que trabalhei, a noção de um erro ocorrendo em qualquer um dos níveis aninhados implicava que qualquer trabalho já realizado era inválido. Ao usar,SAVE TRANSACTION
você está apenas voltando ao estado imediatamente antes da chamada deste Procedimento Armazenado, deixando o processo existente como válido.Se você quiser obter mais detalhes
SAVE TRANSACTION
, consulte as informações nesta resposta:Como reverter quando três procedimentos armazenados são iniciados em um procedimento armazenado
Outro problema
SAVE TRANSACTION
é a nuance de seu comportamento, conforme observado na página do MSDN para SAVE TRANSACTION (ênfase adicionada):Ou seja, você precisa ter muito cuidado para atribuir a cada ponto de salvamento em cada procedimento armazenado um nome exclusivo em todos os pontos de salvamento em todos os procedimentos armazenados. Os exemplos a seguir ilustram esse ponto.
Este primeiro exemplo mostra o que acontece quando você reutiliza o nome do Save Point; somente o Save Point de nível mais baixo é revertido.
Este segundo exemplo mostra o que acontece quando você usa nomes exclusivos de Save Point; o ponto de salvamento do nível desejado é revertido.
fonte