Какой из них более быстрый триггер или хранимая процедура? - PullRequest
0 голосов
/ 30 апреля 2019

В настоящее время у меня есть триггер для каждой таблицы, который обрабатывает журнал истории.Триггер одинаков на каждом столе.См. Ниже.

Если я перенесу это в хранимую процедуру, будет ли она быстрее?

Также, если я использую хранимую процедуру, будет ли запуск спускового механизма для пользователя продолжаться?

create trigger ' + @TABLE_NAME + '_ChangeTracking on ' + @TABLE_NAME + ' for 
insert, update, delete
as
    declare @bit int ,
            @field int ,
            @maxfield int ,
            @char int ,
            @fieldname varchar(128) ,
            @TableName varchar(128) ,
            @PKCols varchar(1000) ,
            @sql nvarchar(max), 
            @Type nvarchar(1) ,
            @PKValueSelect varchar(1000),
            @MasterId nvarchar(max) = ''0''

    select @TableName = ''' + @TABLE_NAME + '''

    if exists(select * from CNF_HIL_Tables where referencetable = @TableName and Active = 1)
    begin
        if exists (select * from inserted)
            if exists (select * from deleted)
                select @Type = ''2''
            else
                select @Type = ''3''
        else
            select @Type = ''1''

        select * into #ins from inserted
        select * into #del from deleted

        select @PKCols = coalesce(@PKCols + '' and'', '' on'') + '' i.'' + c.COLUMN_NAME + '' = d.'' + c.COLUMN_NAME
        from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk 
        inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME
        where pk.TABLE_NAME = @TableName
          and CONSTRAINT_TYPE = ''PRIMARY KEY''

        select @PKValueSelect = coalesce(@PKValueSelect+''+'','''') + ''convert(varchar(100), coalesce(i.'' + COLUMN_NAME + '',d.'' + COLUMN_NAME + ''))''
        from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk    
        inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE c on c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME and c.TABLE_NAME = pk.TABLE_NAME  
        where pk.TABLE_NAME = @TableName   
          and CONSTRAINT_TYPE = ''PRIMARY KEY'' 

        select @field = 0, 
               @maxfield = max(ORDINAL_POSITION) 
        from INFORMATION_SCHEMA.COLUMNS 
        where TABLE_NAME = @TableName

        while @field < @maxfield
        begin
            select @field = min(ORDINAL_POSITION) 
            from INFORMATION_SCHEMA.COLUMNS 
            where TABLE_NAME = @TableName 
              and ORDINAL_POSITION > @field

            select @bit = (@field - 1 )% 8 + 1
            select @bit = power(2,@bit - 1)
            select @char = ((@field - 1) / 8) + 1

            if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in (''1'',''3'')
        begin
            select @fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION = @field

            if exists(select * from CNF_Hil_Columns INNER JOIN CNF_HIL_Tables    ON CNF_HIL_Tables.TablesId = CNF_Hil_Columns.TablesId
                                where CNF_HIL_Tables.referencetable = @TableName  and CNF_Hil_Columns.ColumnName = @fieldname
                                    and CNF_Hil_Columns.Active = 1
                        )
            begin

                if @MasterId = 0
                begin
                    select @sql = ''insert DATA_HIL_Master (OperationType, ReferenceTable, ReferenceId, UserId, WorkstationId, InsDateTime)''
                    select @sql = @sql + '' select '''''' + @Type + ''''''''                                                
                    select @sql = @sql + '', '''''' + @TableName + ''''''''     
                    select @sql = @sql + '','' + @PKValueSelect     
                    select @sql = @sql + '',convert(varchar(1000),i.Last_UserId_Log)''
                    select @sql = @sql + '',convert(varchar(1000),i.Last_WorkstationId_Log)''
                    select @sql = @sql + '',convert(varchar(1000),i.Last_DateTime_Log)''
                    select @sql = @sql + '' from #ins i full outer join #del d''
                    select @sql = @sql + @PKCols 
                    select @sql = @sql + '' SELECT @MasterId = SCOPE_IDENTITY() ''
                    EXECUTE sp_executesql @sql, N''@MasterId nvarchar(max) OUTPUT'', @MasterId OUTPUT
                end

                select @sql = ''insert data_HIL_Detail (MasterId, ColumnName, OriginalValue, ModifiedValue)''
                select @sql = @sql + '' select convert(varchar(1000),'' + @MasterId + '')''
                select @sql = @sql + '','''''' + @fieldname + ''''''''
                select @sql = @sql + '', convert(varchar(1000),d.'' + @fieldname + '')''
                select @sql = @sql + '', convert(varchar(1000),i.'' + @fieldname + '')''
                select @sql = @sql + '' from #ins i full outer join #del d''
                select @sql = @sql + @PKCols

                EXECUTE sp_executesql @sql
            END
        END
    END 
END

1 Ответ

0 голосов
/ 30 апреля 2019

Как правило, независимо от триггера или хранимой процедуры, вы получаете один и тот же код. В триггере вы не можете вызвать его напрямую, а в хранимой процедуре вы вызываете напрямую. Таким образом, независимо от того, используете ли вы триггер или хранимую процедуру, выполнение будет одинаковым. При первом вызове план выполнения кэшируется.

В вашем случае, поскольку вы используете, в частности, использование вставленных, удаленных таблиц, у вас должен быть другой код хранимой процедуры для осуществления аудита. Или вы можете рассмотреть возможность использования временных таблиц SQL Server или Изменение сбора данных или Аудит SQL Server

Но есть несколько недостатков использования триггера.

  • Может сделать транзакцию длиннее
  • Трудно отладить
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...