检查行数据是否已更改

时间:2011-09-07 20:06:21

标签: sql-server database tsql

我的目标: 如果行已更新或已插入新行,则将数据从一个表移动到另一个表。

我有一张桌子我需要某些字段。我需要知道行是否已更新或插入。 Source表没有任何Timestamp字段。我正在使用MSSQL2008。数据来自客户端,他们正在控制表和复制。

我认为我已经弄清楚使用MSSQL 2008的新 Merge 函数,但无论是否有任何更改,它都会更新所有行。这通常不是一个大问题,但我必须添加时间戳字段。无论行是否已更新,我的修改时间字段都将更新。

所以我需要一种方法来完成我的上述目标。我不是一个伟大的SQL专家,所以你可以看到我在努力,任何帮助都会很棒。

USE NaylorAequor
DECLARE CurretDate GetDate();

MERGE Aequor_SLA_Ads AS Target

USING (select AWA.AdOrderID,emp.FirstName, emp.LastName,AWA.VendorID,AO.OrderDate,AO.SaleStatusID,A.AdColorId,AO.PublicationID,AWA.DateAssigned,AWA.DateAdCompleted 
from AdWorkAssignMent as AWA, Employee as emp, AdOrder AS AO,Ad as A
WHERE VendorId = 'Aequor' AND emp.EmployeeID = AWA.EmployeeID AND AWA.AdOrderId = AO.AdOrderID AND AO.AdId = A.AdId) AS Source

ON (Target.AdOrderID = Source.AdOrderID) 

WHEN MATCHED THEN
         UPDATE SET 
            Target.AdOrderID =Source.AdOrderID,
            Target.FirstName = Source.FirstName,
            Target.LastName =Source.LastName,
            Target.VendorID =Source.VendorID,
            Target.OrderDate =Source.OrderDate,
            Target.SaleStatusID =Source.SaleStatusID,
            Target.AdColorId =Source.AdColorId,
            Target.PublicationID =Source.PublicationID,
            Target.DateAssigned =Source.DateAssigned,
            Target.DateAdCompleted =Source.DateAdCompleted,
            Target.AequorModifiedDateTime = GetDate()


WHEN NOT MATCHED BY TARGET THEN
      INSERT (AdOrderID,FirstName,LastName,VendorID,OrderDate,SaleStatusID,AdColorId,PublicationID,DateAssigned,DateAdCompleted,AequorDateTime,AequorModifiedDateTime)

     VALUES (Source.AdOrderID, Source.FirstName,Source.LastName,Source.VendorID, Source.OrderDate,Source.SaleStatusID,Source.AdColorId,
                Source.PublicationID,Source.DateAssigned,Source.DateAdCompleted,GetDate(),GetDate())

OUTPUT $action, Inserted.*, Deleted.*;

2 个答案:

答案 0 :(得分:16)

正如Lamak的回答一样,因为这些不等式比较会变得有点乏味,特别是在列可以为空的情况下,您可能希望用NOT EXISTS(SELECT Source.* INTERSECT SELECT Target.*)替换它们

以下示例用法

declare @t1 table
(
id int,
col2 int NULL
)

declare @t2 table
(
id int,
col2 int NULL
)

INSERT INTO @t1 VALUES(1, NULL),(2,NULL)
INSERT INTO @t2 VALUES(1, NULL),(2,NULL), (3,NULL)

MERGE @t1 AS Target
USING  @t2 AS Source
ON (Target.id = Source.id) 
WHEN MATCHED AND NOT EXISTS(SELECT Source.* INTERSECT SELECT Target.*) THEN
         UPDATE SET 
            Target.id =Source.id
WHEN NOT MATCHED BY TARGET THEN
      INSERT (id)
      VALUES (id)
OUTPUT $action, Inserted.*, Deleted.*;

答案 1 :(得分:5)

如果某些值不同,您需要添加只想更新数据的限制。所以你必须改变查询的那一部分,如下所示:

WHEN MATCHED AND (  Target.FirstName != Source.FirstName OR 
                    Target.LastName != Source.LastName OR
                    Target.VendorID != Source.VendorID OR
                    Target.OrderDate != Source.OrderDate OR
                    Target.SaleStatusID != Source.SaleStatusID OR
                    Target.AdColorId !=Source.AdColorId OR
                    Target.PublicationID !=Source.PublicationID OR
                    Target.DateAssigned !=Source.DateAssigned OR
                    Target.DateAdCompleted !=Source.DateAdCompleted)
THEN
         UPDATE SET 
            Target.AdOrderID =Source.AdOrderID,
            Target.FirstName = Source.FirstName,
            Target.LastName =Source.LastName,
            Target.VendorID =Source.VendorID,
            Target.OrderDate =Source.OrderDate,
            Target.SaleStatusID =Source.SaleStatusID,
            Target.AdColorId =Source.AdColorId,
            Target.PublicationID =Source.PublicationID,
            Target.DateAssigned =Source.DateAssigned,
            Target.DateAdCompleted =Source.DateAdCompleted,
            Target.AequorModifiedDateTime = GetDate()

在这种情况下,比较假设每个字段都不可为空,如果不是这样,你需要将它添加到逻辑中(ISNULL或类似的东西)