我有一个名为user的表,其中包含FirstName,LastName,Age,Location,City,Education等colums
我想做的是
在用户更新其信息后,我想跟踪哪些是用户更新的列。不是更新的行,而是更新的特定行中的确切列。
我创建了一个更新触发器,但它没有给出确切的结果。
Thnaks,
世斌
答案 0 :(得分:2)
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
答案 1 :(得分:-1)
/*******************************************************************************************
* 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