登录到 SQL Server 触发器中的表
Posted
技术标签:
【中文标题】登录到 SQL Server 触发器中的表【英文标题】:Logging into table in SQL Server trigger 【发布时间】:2010-05-11 09:59:28 【问题描述】:我正在编写 SQL Server 2005 触发器。我想在触发器执行期间进行一些日志记录,在我的日志表中使用 INSERT 语句。当执行过程中发生错误时,我想引发错误并取消导致触发器执行的操作,但不丢失日志记录。实现这一目标的最佳方法是什么?
现在我的触发器会记录所有内容,但出现错误时除外 - 因为 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
【问题讨论】:
【参考方案1】:另一个可能的选择是使用表变量来捕获您想要存储在永久日志表中的信息。如果给出 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'
【讨论】:
【参考方案2】:这里的问题是日志记录是修改数据的事务的一部分。嵌套事务在这里无济于事。您需要将记录操作放入单独的上下文(连接)中,即使其独立于您当前的事务。
我想到了两个选项:
使用Service Broker 进行日志记录 - 将日志数据放入队列,接收并保存数据“在管道的另一端”(即在另一个进程/连接/事务中) 使用OPENQUERY - 您需要将自己的服务器注册为“链接服务器”并“远程”执行查询(我知道,这看起来有点奇怪,但无论如何都是一个选项......)HTH
【讨论】:
【参考方案3】:不知道是不是我想的太简单了,为什么不把错误处理程序的顺序改成在回滚之后插入呢??
if (@err = 1)
begin
RAISERROR (@msg, 16, 1)
rollback transaction
INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output
return
end
【讨论】:
【参考方案4】:结帐error handling in triggers。
【讨论】:
以上是关于登录到 SQL Server 触发器中的表的主要内容,如果未能解决你的问题,请参考以下文章