我有一个SQL Server 2008 R2存储过程,它在TRANSACTION中运行一些INSERT和UPDATE。在每个语句之后,我需要在执行下一步之前记录刚刚发生的事情。
这是我的代码:
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO... -- 1st statement
INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 1') -- log
UPDATE... -- 2nd statement
INSERT INTO MyEventLog (EventDescription) VALUES ('Did Step 2') -- log
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (@@TRANCOUNT<>0) ROLLBACK TRANSACTION
EXEC LogError 'I got an error'
END CATCH
问题是:如果出现错误,事务将回滚所有语句 - 包括我需要的日志记录。如果发生错误,如何回滚交易但保留记录。
答案 0 :(得分:1)
我打算问你为什么要记录技术上没有发生的事件,因为事务将被回滚并且数据库将处于事务之前的状态。但后来我发现你可能只是想记录它以便知道它失败了,所以你可以解决潜在的问题,这是一个聪明的事情。
如果确实如此,最好的办法是回滚当前正在执行的整个事务,并使用LogError SP在另一个表中记录错误消息。这就是我使用的:
CREATE PROCEDURE [dbo].[Error_Handler]
@returnMessage bit = 'False'
WITH EXEC AS CALLER
AS
BEGIN
DECLARE @number int,
@severity int,
@state int,
@procedure varchar(100),
@line int,
@message varchar(4000)
INSERT INTO Errors (Number,Severity,State,[Procedure],Line,[Message])
VALUES (
ERROR_NUMBER(),
ERROR_SEVERITY(),
ERROR_STATE(),
isnull(ERROR_PROCEDURE(),'Ad-Hoc Query'),
isnull(ERROR_LINE(),0),
ERROR_MESSAGE())
IF(@returnMessage = 'True')
BEGIN
select *
from Errors
where ErrorID = scope_identity()
END
END
错误消息可以让您知道在哪个表中出现了什么问题,并且 应该足以解决问题。
答案 1 :(得分:1)
见Logging messages during a transaction。有点令人费解:
但它确实允许您在事务期间记录消息,即使事务回滚,消息也会保留。记录顺序保留。
当一个程序失败但事务可以继续时(例如,处理批处理和一个项目失败时,您希望继续完成批处理的其余部分),您还需要使事务和存储过程发挥得很好。请参阅Exception handling and nested transactions。
答案 2 :(得分:0)
如何将日志记录语句放入单独的事务中?
我把它放在CATCH块中:
BEGIN CATCH
IF (@@TRANCOUNT<>0)
ROLLBACK TRANSACTION
EXEC LogError 'I got an error'
BEGIN TRANSACTION
INSERT INTO MyEventLog (EventDescription) VALUES ('Error Updating') -- log
END TRANSACTION
END CATCH
答案 3 :(得分:0)
事实证明,表变量不遵循事务语义。因此,您可以插入表变量,然后在catch块之后将表变量插入到日志表中。