需要比较两行的差异吗?

时间:2012-02-09 07:35:48

标签: tsql stored-procedures iteration

我需要将两行相互比较,然后将更改的字段写入表中。

我的表:

CREATE TABLE dbo.tUserChanges
(
cID int IDENTITY (1,1),
cChangeDate DateTime,
cValueChanged varchar(30),
cPreviousValue bit,
cCurrentValue bit
)

在我的C#程序中,当对用户进行更改时,需要更新用户表。

这是通过存储过程完成的:

CREATE PROCEDURE [dbo].[UUser]       
( 
 @User as varchar(15),   
 @UCode  AS int,      
 @UName  AS varchar(30),      
 @UID   AS  varchar(10),      
 @UPassword  AS varchar(15),      
 @UPMaintenance as bit,      
 @UClient  as bit,      
 @UFinancial  as bit,      
 @UViewReceiptImage bit,
 @UViewPayrollData bit
) 
AS
BEGIN
UPDATE  tUsers      
 SET        
 UName    = @UName,      
 UID    = @UID,      
 UPassword   = @UPassword,  UPMaintenance   = @UPMaintenance,       
 UClient    = @UClient,      
 UFinancial   = @UFinancial,
 UViewReceiptImage = @UViewReceiptImage,
 UViewPayrollData = @UViewPayrollData     
 WHERE UCode = @UCode 
END 

tUser表中有更多值,但为了保持排序,我删除了一些值。

所以我需要做的是在befor更新tUsers表时创建一个临时表,这样我就可以在更新完成后比较两行,然后将发生的更改改为新表。 / p>

我试过这个,但我知道有更好的方法,它也没有给出所需的结果:

declare @i int
set @i = 0
declare @ColumnCount int
set @ColumnCount = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE  table_name = @UID)
declare @ColumnName varchar(30)
set @ColumnName = (select column_name from information_schema.columns  where table_name = 'tUsers' and ordinal_position = 14)

select UActivateLoan from tusers

while (@ColumnCount < @i)
Begin
    if((select @ColumnName from tUsers where UID = @UID) 
    <> (select @ColumnName from #myTemp where UID = @UID))
    Begin
        Insert into tUserChanges
        Values(GETDATE(),(select column_name from information_schema.columns  where table_name = 'tUsers' and ordinal_position = 14),
                (select(select column_name from information_schema.columns  where table_name = 'tUsers' and ordinal_position = 14) from #myTemp where UID = @UID),
                (select(select column_name from information_schema.columns  where table_name = 'tUsers' and ordinal_position = 14) from tUsers where UID = @UID))
    END
    set @i = @i + 1
End

我不确定我是否需要在这里使用光标或我可以做些什么来获得结果? 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

使用FOR UPDATE触发器可以做得更好。

CREATE TRIGGER dbo.tUser_AfterUpdate ON dbo.tUsers FOR UPDATE AS 
BEGIN
  IF UPDATE(UName) THEN 
    INSERT INTO tUserChanges 
    SELECT GETDATE()
           , (SELECT UName FROM DELETED) -- Old Value
           , (SELECT UName FROM INSERTED) -- New Value

  ...
END

CREATE TRIGGER

  

创建一个触发器,它是一种特殊的存储过程   当用户尝试指定时自动执行   指定表上的数据修改语句。 Microsoft®SQL   Server™允许为任何给定的INSERT创建多个触发器,   UPDATE或DELETE语句。

修改

使用动态SQL,就像

  CREATE TRIGGER dbo.tUser_AfterUpdate ON dbo.tUsers FOR UPDATE AS 
  BEGIN
    DECLARE @Columns TABLE (name sysname)
    DECLARE @ColumnName sysname
    DECLARE @Statement VARCHAR(MAX)

    INSERT INTO @Columns
    SELECT  name
    FROM    sys.columns
    WHERE   OBJECT_NAME(OBJECT_ID) = 'tUsers'

    WHILE EXISTS (SELECT * FROM @Columns)
    BEGIN 
      SELECT TOP 1 @ColumnName = name FROM @Columns
      DELETE FROM @Columns WHERE name = @ColumnName

      SET @Statement = 
        'IF UPDATE(' + @ColumnName + ') THEN '
        + 'INSERT INTO tUserChanges '
        + 'SELECT GETDATE() '
        + '      , (SELECT ' + @ColumnName + 'FROM DELETED) -- Old Value'
        + '      , (SELECT ' + @ColumnName + 'FROM INSERTED) -- New Value'

      EXEC (@Statement)
    END
  END