2010-05-11 124 views
4

我正在编写SQL Server 2005触发器。我想在触发器执行期间做一些日志记录,在我的日志表中使用INSERT语句。当执行过程中出现错误时,我想提出错误并取消导致触发器执行的操作,但不会丢失日志记录。达到此目的的最佳方法是什么?在SQL Server中登录表触发器

现在我的触发器会记录除了情况发生错误时的所有事情 - 因为ROLLBACK。需要RAISERROR语句来通知调用程序有关错误。

现在,我的错误处理代码如下所示:

if (@err = 1) 
begin 
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output 
    RAISERROR (@msg, 16, 1) 
    rollback transaction 
    return 
end 

回答

7

另一种可能的选择是使用表变量捕获您想要存储在永久日志表中的信息。如果给出ROLLBACK TRANSACTION命令,表格变量不会回滚。示例代码如下...



--- Declare table variable 
DECLARE @ErrorTable TABLE 
    ([DATE] smalldatetime, 
    [ENTRY] varchar(64)) 

DECLARE @nErrorVar int 

--- Open Transaction 
BEGIN TRANSACTION 

--- Pretend to cause an error and catch the error code 
SET @nErrorVar = 1 --- @@ERROR 

IF (@nErrorVar = 1) 
    BEGIN 

    --- Insert error info table variable 
    INSERT INTO @ErrorTable 
     ([Date], [Entry]) 
    SELECT 
     getdate(), 'Error Message Goes Here' 

    RAISERROR('Error Message Goes Here', 16, 1) 

    ROLLBACK TRANSACTION 

    --- Change this to actually insert into your permanent log table 
    SELECT * 
    FROM @ErrorTable 

    END 

IF @@TRANCOUNT 0 
    PRINT 'Open Transactions Exist' 
ELSE 
    PRINT 'No Open Transactions' 
+0

这就是我们做的 – HLGEM 2010-05-11 19:58:45

+0

的确。我错过了这个选项,但是投了票。 – AlexS 2010-05-11 20:04:02

2

这里的问题是,日志记录是修改数据的交易的一部分。嵌套事务在这里没有帮助。您需要的是将日志记录操作放入单独的上下文(连接)中,即使其独立于当前事务。

两个选项来我的脑海:

  • 使用Service Broker的记录 - 把数据记录到队列中,接收并保存“在管道的另一端”的数据(即在另一个进程/连接/交易)
  • 使用OPENQUERY - 你需要注册你自己的服务器作为一个“链接服务器”,并执行查询“远程”(我知道,这看起来有点怪怪的,但一个选项无论如何...)

HTH

2

不知道如果我想得简单,但为什么不只是改变错误处理程序的顺序插入回滚后?

if (@err = 1) 
begin 
    RAISERROR (@msg, 16, 1) 
    rollback transaction 
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output 
    return 
end 
+0

投票+1为简单XD – 2011-12-15 18:01:13