【问题标题】:Stored procedure inside a trigger for logging用于记录的触发器内的存储过程
【发布时间】:2022-01-26 02:03:32
【问题描述】:

我对多个表使用相同的触发器来记录 DML 事件,因此我有很多冗余代码。如何编写存储过程并在这些触发器中调用它来记录数据?

这是我的触发器的样子

CREATE OR ALTER TRIGGER [Person].tr_logInsertDeleteOrUpdateemployee
ON [Person].employee
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @tableName varchar(100) = '[Person].employee'

    IF EXISTS (SELECT TOP 1 * FROM inserted) 
       AND EXISTS (SELECT TOP 1 * FROM Deleted)
    BEGIN
        INSERT INTO dbo.DMLLogs
            SELECT updatedRecord = 'updated row', @tableName, ID, SYSTEM_USER, GETDATE()  
            FROM deleted
    END

    IF EXISTS (SELECT TOP 1 * FROM inserted) 
       AND NOT EXISTS (SELECT TOP 1 * FROM Deleted)
    BEGIN
        INSERT INTO dbo.DMLLogs
            SELECT insertedRecord = 'inserted', @tableName, ID, SYSTEM_USER, GETDATE() 
            FROM inserted
    END

    IF EXISTS (SELECT TOP 1 * FROM deleted) 
       AND NOT EXISTS (SELECT TOP 1 * FROM inserted)
    BEGIN
        INSERT INTO dbo.DMLLogs
            SELECT deletedRecord = 'deleted from', @tableName, ID, SYSTEM_USER, GETDATE() 
            FROM deleted
    END
END

【问题讨论】:

  • 触发器很昂贵。对于每个已知日志记录操作的触发器,我将有 3 个特定的触发器,而无需重复查询虚拟表。此外,您是否考虑过使用临时表,它可以为您提供很多您已经拥有的东西,甚至更多。
  • @shokomoko 使用触发器会大大降低您的性能并减慢您对大量用户的查询。通过程序插入或编辑时最好插入日志操作。这是因为在批量插入或批量更新期间必须以非常复杂的方式设计触发器,这会导致您在开发过程中遇到的数据库性能问题。
  • 如果您必须在数据库中执行此操作,或许临时表会是更好的选择。

标签: sql sql-server logging stored-procedures triggers


【解决方案1】:

撇开是否有比创建触发器更好的选择不谈,插入和删除的虚拟表在存储过程中是不可见的,因此实际上没有办法做到这一点。通常的做法是自动创建样板触发器,因此它们都是从单个模板创建的。比如:

create schema admin
go
create or alter proc admin.GenerateAuditingTriggers
as
begin
    declare c cursor local for
    select name, schema_name(schema_id)
    from sys.tables 
    where schema_id in (schema_id('dbo'))
    
    open c
    declare @tableName sysname
    declare @schemaName sysname

    fetch next from c into @tableName, @schemaName 
    while @@FETCH_STATUS = 0
    begin
        declare @sql nvarchar(max) = concat(
        '
        CREATE OR ALTER TRIGGER  ',quotename(@schemaName),'.',quotename('tr_logInsert' + @tableName),'
        ON ',quotename(@schemaName),'.',quotename(@tableName),'
        AFTER INSERT
        AS
        BEGIN
            SET NOCOUNT ON

            DECLARE @tableName varchar(100) = ''',quotename(@schemaName),'.',quotename(@tableName),'''
            INSERT INTO dbo.DMLLogs
            SELECT updatedRecord = ''inserted row'', @tableName, ID, SYSTEM_USER, GETDATE()  
            FROM inserted
        END
        ')
        print @sql
        exec (@sql)
        print 'trigger created'
        print ''
        fetch next from c into @tableName, @schemaName 
    end
    close c 
    deallocate c
end

【讨论】:

    猜你喜欢
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2018-01-18
    • 2013-09-12
    • 1970-01-01
    相关资源
    最近更新 更多