触发器内的事务独立写入

Ser*_*est 5 trigger sql-server-2008 sql-server-express

我使用的是 sql express 2008 r2 express 版。

是否可以独立于导致触发器触发的语句的事务在触发器内部进行写入?

我有触发器用于对我的数据库中的某些表进行简单审计。我有一张用于保存审计数据的表(查看此处了解详细信息)它工作正常,除非我不希望在事务回滚时审计数据消失。所以我想将审计数据写入审计表,独立于导致我的审计触发器触发的语句的事务。

And*_*mar 1

一种解决方案是向您自己的服务器添加链接服务器。在链接服务器上,禁用事务。对链接服务器进行的任何调用现在都将在其自己的事务中运行。

设置示例:

-- Add linked server called LOCALHOST
USE [master]
IF  EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'LOCALHOST')
    EXEC master.dbo.sp_dropserver @server=N'LOCALHOST', @droplogins='droplogins'

EXEC master.dbo.sp_addlinkedserver @server = N'LOCALHOST', @srvproduct=N'SQL Server'
-- Allow procedure calls
EXEC master.dbo.sp_serveroption @server=N'LOCALHOST', @optname=N'rpc out', @optvalue=N'true'
-- But do not allow the procedure calls to enlist in our transaction
EXEC master.dbo.sp_serveroption @server=N'LOCALHOST', @optname=N'remote proc transaction promotion', @optvalue=N'false'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'LOCALHOST', @locallogin = NULL , @useself = N'true'

-- Create a test procedure
use TestDatabase
if exists (select * from sys.tables where name = 'Log')
    drop table log
if exists (select * from sys.procedures where name = 'WriteLog')
    drop procedure WriteLog
go
create table log (id int identity, message varchar(256))
go
create procedure WriteLog
as
insert Log (message) values ('Hello World!')
go
Run Code Online (Sandbox Code Playgroud)

测试代码:

-- Insert through a direct call, and then through a linked server call
begin transaction
exec TestDatabase.dbo.WriteLog
exec [Localhost].TestDatabase.dbo.WriteLog
rollback transaction

select * from Log
Run Code Online (Sandbox Code Playgroud)

select仅显示 1 行。尚未rollback撤消链接服务器调用的影响。

虽然这是一个不错的技巧,但您可能不想在生产环境中执行此操作。就我个人而言,我只允许通过存储过程修改数据,并在启动事务(如果有)之前在存储过程本身中添加日志记录。