是的,您可以这样做,但有一些复杂性和限制。这不是建议,只是一个答案。
SQLServer 提供了内置函数,例如 ERROR_MESSAGE()、ERROR_NUMBER() 以在 catch 块中使用。
如果您的插入/删除代码在自动提交模式下运行(没有开始传输,没有隐式事务),那么只需在 catch 块中记录错误消息和编号就可以了,因为插入和删除已经回滚或提交。
所以
begin try
-- do work
end try
begin catch
insert into audit_table select ERROR_MESSAGE(), ERROR_NUMBER()
end catch
能行得通。
如果您的 TSQL 代码或客户端使用 begin tran 或隐式事务,catch 块中的逻辑必须考虑这一点,否则回滚原始事务时将回滚错误记录,不留下任何错误记录。
如果你有这样的...
begin try
begin tran
-- do work
if xact_state() = 1 commit tran
if xact_state() = -1 rollback tran
end try
begin catch
-- Now there is a good chance a transaction is still pending or uncomittable.
if xact_state() != 0 rollback tran -- assuming you always rollback.
-- Insert will be recorded because previous transaction was cleared.
insert into audit_table select ERROR_MESSAGE(), ERROR_NUMBER()
end catch
如果您在 catch 块中不提交或回滚,并且您的事务是不可提交的,那么您的插入最终会回滚,并且您没有错误记录。
如果客户端正在管理事务,则可能无法记录错误信息,除非客户端对您的错误处理程序发出回滚没有问题。并且发出回滚本身可能会产生掩盖真正根本原因的错误。如果不考虑复杂性,如果客户端正在管理事务,那么让客户端也可以更容易地捕获和记录错误。