Как исправить триггер аудита, не фиксируя изменения для одного столбца - PullRequest
0 голосов
/ 30 января 2019

У меня есть триггер для аудита вставок, удалений и обновлений.Я изменил онлайн-скрипт для этого.Сценарии прекрасно работают без каких-либо модификаций, но для бизнес-требований я внес несколько изменений.Для 9 таблиц во всей моей базе данных этот триггер имеет пользовательские изменения.Триггер работает отлично для всех 8 таблиц, кроме 1. 1 таблица, для которой он вызывает проблемы, предназначена только для 1 столбца.

Моя таблица содержит следующие столбцы:

CREATE TABLE [d2c].[linkage_profile](
    [linkage_profile_id] [int] IDENTITY(1,1) NOT NULL Primary Key,
    [first_name] [nvarchar](250) NULL,
    [last_name] [nvarchar](250) NULL,
    [middle_name] [nvarchar](250) NULL,
    [suffix] [nvarchar](50) NULL,
    [is_pregnant] [bit] NULL,
    [expected_date] [datetime2](7) NULL,
    [user_id] [int] NOT NULL,
    [is_grace_period] [bit] NOT NULL,
    [closed_date] [datetime2](7) NULL,
    [birth_gender_id] [int] NOT NULL,
    [status_id] [int] NOT NULL,
    [assigned_date] [datetime2](7) NULL,
    [created_by] [nvarchar](50) NULL,
    [date_created] [datetime2](7) NOT NULL,
    [modified_by] [nvarchar](50) NULL,
    [date_modified] [datetime2](7) NULL,
    [state_no] [nvarchar](20) NULL,
    [county_id] [int] NULL,
    [area_name] [nvarchar](3) NULL,
    [ehars_client_profile_id] [int] NULL,
    [priority_id] [int] NULL,
    [assigned_by] [nvarchar](50) NULL,

Это триггер, который я использую:

Alter TRIGGER [d2c].[tr_linkage_profile] ON d2c.linkage_profile FOR INSERT, UPDATE, DELETE

AS
SET NOCOUNT ON

DECLARE @bit INT ,
@field INT ,
@fieldId INT ,
@maxfield INT ,
@char INT ,
@fieldname VARCHAR(128) ,
@FieldDisplayName VARCHAR(128),
@TableDisplayName VARCHAR(128),
@SchemaName VARCHAR(128) ,
@TableName VARCHAR(128) ,
@PKCols VARCHAR(1000) ,
@sql VARCHAR(5000), 
@UpdateDate VARCHAR(21) ,
@UserName VARCHAR(128) ,
@Type CHAR(1) ,
@PKSelect VARCHAR(1000) ,
@linkageID VARCHAR(1000) ,
@FullTableName VARCHAR(256),
@oldvalue VARCHAR(1000),
@newvalue VARCHAR(1000),
@oldvalue1 VARCHAR(1000),
@newvalue1 VARCHAR(1000),
--@modified_by VARCHAR(20)='modified_by',
@isviewable char(1),
@next bit

SELECT @TableName = 'linkage_profile' , @schemaName = 'd2c'

SELECT @FullTableName = @SchemaName + '.' + @TableName

-- date and user
SELECT @UserName = SYSTEM_USER ,
@UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112) 
+ ' ' + CONVERT(VARCHAR(12), GETDATE(), 114)

-- Action
IF EXISTS (SELECT * FROM inserted)
IF EXISTS (SELECT * FROM deleted)
SELECT @Type = 'U'

    ELSE
        SELECT @Type = 'I'
    ELSE
SELECT @Type = 'D'

-- get list of columns
SELECT * INTO #ins FROM inserted
SELECT * INTO #del FROM deleted


-- Get primary key columns for full outer join
SELECT @PKCols = COALESCE(@PKCols + ' and', ' on') 
+ ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = @TableName
AND pk.TABLE_SCHEMA = @SchemaName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
AND c.CONSTRAINT_SCHEMA = pk.TABLE_SCHEMA

-- Get primary key select for insert
SELECT @PKSelect = COALESCE(@PKSelect+'+','') + '''' +
 '''+convert(varchar(100),coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+''''' 
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = @TableName
AND pk.TABLE_SCHEMA = @SchemaName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
AND c.CONSTRAINT_SCHEMA = pk.TABLE_SCHEMA

-- Get client id select for insert
if @FullTableName <> 'd2c.ehars_client_profile'
BEGIN
SELECT @linkageID = COALESCE(@linkageID+'+','') + '''' + 
 '''+convert(varchar(100),coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))+''''' 
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE c.TABLE_NAME = @TableName
AND c.TABLE_SCHEMA = @SchemaName
AND c.COLUMN_NAME = 'linkage_profile_id'
END

if @FullTableName = 'd2c.ehars_client_profile'
SELECT @linkageID = 'NULL'


IF @PKCols IS NULL
BEGIN
RAISERROR('no PK on table %s', 16, -1, @FullTableName)
RETURN
END
---------------------Display value for table
SET @TableDisplayName = 'Linkage Profile Data'

--------------------------
SELECT @field = 0, 
@maxfield = MAX(ORDINAL_POSITION) 
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = @SchemaName

WHILE @field < @maxfield
BEGIN
SELECT @fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = @TableName
    AND TABLE_SCHEMA = @SchemaName
    AND ORDINAL_POSITION = @field

SELECT @fieldid = COLUMNPROPERTY(OBJECT_ID(@FullTableName), @fieldname, 'ColumnID')

SELECT @field = MIN(ORDINAL_POSITION) 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = @TableName 
AND TABLE_SCHEMA = @SchemaName
AND ORDINAL_POSITION > @field
select @bit = (@fieldid - 1 )% 8 + 1
select @bit = power(2,@bit - 1)
select @char = ((@fieldid - 1) / 8) + 1


----
--select TABLE_NAME, COLUMN_NAME from  INFORMATION_SCHEMA.COLUMNS where TABLE_NAME in ('barrier_client',    'client_attempt','disposition', 'ehars_client_profile', 'note_attachement', 'linkage_profile',  'provider_attempt', 'referral_client',  'result')


--------------display values for fields
    SET @FieldDisplayName = CASE @fieldname --I have a lot of case statement here, removed to keep it short
            WHEN 'assigned_by' THEN 'Assigned By'
        WHEN 'assigned_date' THEN 'Assigned Date'
            END

-- Managing Is viewable field for all types
 select @isviewable = '0'
 ----------
 if @type in('U')
 begin
 select @isviewable = '1'
 end
 -----------
if @type in('D')
if @fieldname in ('referral_id','other_desc','barrier_id')
       Begin
                select @IsViewable='1'
       End
 -----------
if @fieldname  in ('created_by','date_created')
        Begin
                select @IsViewable='0'
       End
 -----------setting next at default 0
Select @next = 0
--------------------------------field specific values 5 Linkage Profile
        if @fieldname = 'User_ID'
            BEGIN
                select @oldvalue =c.first_name from [d2c].[user] c inner join deleted d on d.User_ID = c.User_ID
                select @oldvalue1 =c.last_name from [d2c].[user] c inner join deleted d on d.User_ID = c.User_ID
                Select @oldvalue = CONCAT (@oldvalue , ' ', @oldvalue1)
                if @oldvalue = 'd.expected_date '  set @oldvalue = 'NULL'

                select @newvalue = c.first_name from [d2c].[user] c inner join inserted i on i.User_ID = c.User_ID
                select @newvalue1 =c.last_name from [d2c].[user] c inner join inserted i on i.User_ID = c.User_ID
                Select @newvalue = CONCAT (@newvalue , ' ', @newvalue1)
                if @newvalue = 'i.expected_date '  set @newvalue = 'NULL'
                Select @next = 1

            end

        if @fieldname = 'birth_gender_id'
            BEGIN
                select @oldvalue =c.name from lu.birth_gender c inner join deleted d on d.birth_gender_id = c.birth_gender_id
                if @oldvalue = 'd.closed_date'  set @oldvalue = 'NULL'

                select @newvalue = c.name from lu.birth_gender c inner join inserted i on i.birth_gender_id = c.birth_gender_id
                if @newvalue = 'i.closed_date'  set @newvalue = 'NULL'
                Select @next = 1

            end

        if @fieldname = 'Status_ID'
            BEGIN
                select @oldvalue =c.status_name from lu.status c inner join deleted d on d.Status_ID = c.Status_ID
                if @oldvalue = 'd.closed_date'  set @oldvalue = 'NULL'

                select @newvalue = c.status_name from lu.status c inner join inserted i on i.Status_ID = c.Status_ID
                if @newvalue = 'i.closed_date'  set @newvalue = 'NULL'
                Select @next = 1

            end
            if @fieldname = 'county_id'
            BEGIN
                select @oldvalue =c.name from lu.county c inner join deleted d on d.county_id = c.county_id
                if @oldvalue = 'd.state_no'  set @oldvalue = 'NULL'

                select @newvalue = c.name from lu.county c inner join inserted i on i.county_id = c.county_id
                if @newvalue = 'i.state_no'  set @newvalue = 'NULL'
                Select @next = 1

            end

                if @fieldname = 'priority_id'
            BEGIN
                select @oldvalue =c.priority_name from lu.priority c inner join deleted d on d.priority_id = c.priority_id
                if @oldvalue = 'd.ehars_client_profile_id'  set @oldvalue = 'NULL'

                select @newvalue = c.priority_name from lu.priority c inner join inserted i on i.priority_id = c.priority_id
                if @newvalue = 'i.ehars_client_profile_id'  set @newvalue = 'NULL'
                Select @next = 1

            end

--------------------------------------------------------------------------running field specific value in insert
    If @next = 1

    if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in ('I','D')
    print substring(COLUMNS_UPDATED(),@char, 1);
        BEGIN
        SELECT @sql = '
        insert d2c.Audit_client_Data ( Type,TableSchema,TableName,tabledisplayname,fielddisplayname, 
        PK, linkage_profile_id,is_viewable,FieldName, OldValue, NewValue, 
        UpdateDate, UserName,Application)
        select ''' + @Type + ''','''+ @SchemaName  + ''',''' + @TableName + ''','''  + @TableDisplayName  + '''
        ,'''   + @FieldDisplayName  + ''','    + @PKSelect + ',' + @linkageID + ', ' + @isviewable+' 
        ,''' + @fieldname  + ''''+ ', ''' +@oldvalue+''', ''' +@newvalue+''', ' + '''' + @UpdateDate  + ''''+ '
        ,'''  + @UserName + ''''+ ',''' + REPLACE(APP_NAME(), '''', '''''') + '''' + 
        ' from #ins i full outer join #del d'+ @PKCols+ ' where i.' + @fieldname + ' <> d.' + @fieldname + ' or (i.' + @fieldname + ' is null and d.'+ @fieldname + ' is not null)' + ' or (i.' + @fieldname + ' is not null and d.' + @fieldname + ' is null)' 

        EXEC (@sql)

    END

--------------------condition 1 change this for each trigger

if  @next = 0 
if @fieldname not in ('modified_by','date_modified')
        if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in ('I','D')

            BEGIN

                select @oldvalue ='d.'+@fieldname
                select @newvalue = 'i.'+@fieldname
                SELECT @sql = '
                insert d2c.Audit_client_Data ( Type,TableSchema,TableName,tabledisplayname,fielddisplayname, 
                PK, linkage_profile_id,is_viewable,FieldName, OldValue, NewValue, 
                UpdateDate, UserName,Application)
                select ''' + @Type + ''','''+ @SchemaName  + ''',''' + @TableName + ''','''  + @TableDisplayName  + '''
                ,'''   + @FieldDisplayName  + ''','    + @PKSelect + ',' + @linkageID+ ', ' + @isviewable+' 
                ,''' + @fieldname  + ''''+ ', ' +@oldvalue+', ' +@newvalue+', ' + '''' + @UpdateDate  + ''''+ '
                ,'''  + @UserName + ''''+ ',''' + REPLACE(APP_NAME(), '''', '''''') + '''' + 
                ' from #ins i full outer join #del d'+ @PKCols+ ' where i.' + @fieldname + ' <> d.' + @fieldname + ' or (i.' + @fieldname + ' is null and d.'+ @fieldname + ' is not null)' + ' or (i.' + @fieldname + ' is not null and d.' + @fieldname + ' is null)' 
                EXEC (@sql)


            END
---------------------
END

Когда я обновляю, вставляю или удаляю все столбцы, триггер обрабатывает все, кроме последнего столбца Assigned_by.Я не могу понять, в чем проблема.он не проходит через этот код

"if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in ('I','D')" which is at the very bottom. HELP!!! 
...