【问题标题】:How to get updated column names in sql server如何在 sql server 中获取更新的列名
【发布时间】:2011-11-08 11:40:03
【问题描述】:

我有一个名为 user 的表,其中包含 FirstName、LastName、Age、Location、City、Education 等列

我想做的是

在用户更新他的信息后,我想跟踪哪些是用户更新的列。不是更新的行,而是特定行中更新的确切列。

我创建了一个更新触发器,但它没有给出确切的结果。

感谢,

世斌

【问题讨论】:

  • UPDATED 是指包含在UPDATE 语句中还是实际上已更改?另外请提供完整的表结构和到目前为止的触发器。你想用这些信息做什么?
  • UPDATED 表示实际更改的列

标签: sql-server triggers


【解决方案1】:
DECLARE @idTable INT
SELECT @idTable = T.id FROM sysobjects P JOIN sysobjects T ON P.parent_obj = T.id WHERE P.id = @@procid
DECLARE @Columns_Updated VARCHAR(50)

SELECT  @Columns_Updated = ISNULL(@Columns_Updated + ', ', '') + name
FROM    syscolumns
WHERE   id = @idTable
AND     CONVERT(VARBINARY,REVERSE(COLUMNS_UPDATED())) & POWER(CONVERT(BIGINT, 2), colorder - 1)  > 0

【讨论】:

    【解决方案2】:
    /*******************************************************************************************
    *         Add the below table to your database to track data changes using the trigger    *
    *         below. Remember to change the variables in the trigger to match the table that  *
    *         will be firing the trigger                                                      *
    *******************************************************************************************/
    SET ANSI_NULLS ON;
    GO
    
    SET QUOTED_IDENTIFIER ON;
    GO
    
    CREATE TABLE [dbo].[AuditDataChanges]
    (
      [RecordId] [INT] IDENTITY(1, 1)
                       NOT NULL ,
      [TableName] [VARCHAR](50) NOT NULL ,
      [RecordPK] [VARCHAR](50) NOT NULL ,
      [ColumnName] [VARCHAR](50) NOT NULL ,
      [OldValue] [VARCHAR](50) NULL ,
      [NewValue] [VARCHAR](50) NULL ,
      [ChangeDate] [DATETIME2](7) NOT NULL ,
      [UpdatedBy] [VARCHAR](50) NOT NULL ,
      CONSTRAINT [PK_AuditDataChanges] PRIMARY KEY CLUSTERED
        ( [RecordId] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
    )
    ON  [PRIMARY];
    
    GO
    
    ALTER TABLE [dbo].[AuditDataChanges] ADD  CONSTRAINT   [DF_AuditDataChanges_ChangeDate]  DEFAULT (GETDATE()) FOR [ChangeDate];
    GO
    
    
    
    /************************************************************************************************
    * Add the below trigger to any table you want to audit data changes on. Changes will be saved   *
    * in the  AuditChangesTable.                                                                    *
    *************************************************************************************************/
    ALTER TRIGGER trg_Survey_Identify_Updated_Columns ON Survey --Change to match your table name
    FOR INSERT, UPDATE
    AS
    SET NOCOUNT ON;
    
    DECLARE @sql VARCHAR(5000) ,
        @sqlInserted NVARCHAR(500) ,
        @sqlDeleted NVARCHAR(500) ,
        @NewValue NVARCHAR(100) ,
        @OldValue NVARCHAR(100) ,
        @UpdatedBy VARCHAR(50) ,
        @ParmDefinitionD NVARCHAR(500) ,
        @ParmDefinitionI NVARCHAR(500) ,
        @TABLE_NAME VARCHAR(100) ,
        @COLUMN_NAME VARCHAR(100) ,
        @modifiedColumnsList NVARCHAR(4000) ,
        @ColumnListItem NVARCHAR(500) ,
        @Pos INT ,
        @RecordPk VARCHAR(50) ,
        @RecordPkName VARCHAR(50);
    
    SELECT  *
    INTO    #deleted
    FROM    deleted;
    SELECT  *
    INTO    #Inserted
    FROM    inserted;
    
    SET @TABLE_NAME = 'Survey'; ---Change to your table name
    SELECT  @UpdatedBy = UpdatedBy --Change to your column name for the user update field
    FROM    inserted;
    SELECT  @RecordPk = SurveyId --Change to the table primary key field
    FROM    inserted;   
    SET @RecordPkName = 'SurveyId';
    SET @modifiedColumnsList = STUFF(( SELECT   ',' + name
                                       FROM     sys.columns
                                       WHERE    object_id = OBJECT_ID (@TABLE_NAME)
                                                AND SUBSTRING(COLUMNS_UPDATED(),
                                                              ( ( column_id
                                                              - 1 ) / 8 + 1 ),
                                                              1) & ( POWER(2,
                                                              ( ( column_id
                                                              - 1 ) % 8 + 1 )
                                                              - 1) ) = POWER(2,
                                                              ( column_id - 1 )
                                                              % 8)
                                     FOR
                                       XML PATH('')
                                     ), 1, 1, '');
    
    
    WHILE LEN(@modifiedColumnsList) > 0
        BEGIN
            SET @Pos = CHARINDEX(',', @modifiedColumnsList);
            IF @Pos = 0
                BEGIN
                    SET @ColumnListItem = @modifiedColumnsList;
                END;
            ELSE
                BEGIN
                    SET @ColumnListItem = SUBSTRING(@modifiedColumnsList, 1,
                                                    @Pos - 1);
                END;    
    
            SET @COLUMN_NAME = @ColumnListItem;
            SET @ParmDefinitionD = N'@OldValueOut NVARCHAR(100) OUTPUT';
            SET @ParmDefinitionI = N'@NewValueOut NVARCHAR(100) OUTPUT';
            SET @sqlDeleted = N'SELECT @OldValueOut=' + @COLUMN_NAME
                + ' FROM #deleted where ' + @RecordPkName + '='
                + CONVERT(VARCHAR(50), @RecordPk);
            SET @sqlInserted = N'SELECT @NewValueOut=' + @COLUMN_NAME
                + ' FROM #Inserted where ' + @RecordPkName + '='
                + CONVERT(VARCHAR(50), @RecordPk);
            EXECUTE sp_executesql @sqlDeleted, @ParmDefinitionD,
                @OldValueOut = @OldValue OUTPUT;
            EXECUTE sp_executesql @sqlInserted, @ParmDefinitionI,
                @NewValueOut = @NewValue OUTPUT;
            IF ( LTRIM(RTRIM(@NewValue)) != LTRIM(RTRIM(@OldValue)) )
                BEGIN   
                    SET @sql = 'INSERT INTO [dbo].[AuditDataChanges]
                                                   ([TableName]
                                                   ,[RecordPK]
                                                   ,[ColumnName]
                                                   ,[OldValue]
                                                   ,[NewValue]
                                                   ,[UpdatedBy])
                                             VALUES
                                                   (' + QUOTENAME(@TABLE_NAME, '''') + '
                                                   ,' + QUOTENAME(@RecordPk, '''') + '
                                                   ,' + QUOTENAME(@COLUMN_NAME, '''') + '
                                                   ,' + QUOTENAME(@OldValue, '''') + '
                                                   ,' + QUOTENAME(@NewValue, '''') + '
                                                   ,' + QUOTENAME(@UpdatedBy, '''') + ')';
    
    
                    EXEC (@sql);
                END;     
            SET @COLUMN_NAME = '';
            SET @NewValue = '';
            SET @OldValue = '';
            IF @Pos = 0
                BEGIN
                    SET @modifiedColumnsList = '';
                END;
            ELSE
                BEGIN
               -- start substring at the character after the first comma
                    SET @modifiedColumnsList = SUBSTRING(@modifiedColumnsList,
                                                         @Pos + 1,
                                                         LEN(@modifiedColumnsList)
                                                         - @Pos);
                END;
        END;
    DROP TABLE #Inserted;
    DROP TABLE #deleted;
    
    GO
    

    【讨论】:

      猜你喜欢
      • 2011-04-08
      • 2021-04-02
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      相关资源
      最近更新 更多