我正在创建一个ASP.net web应用程序,它从用户那里接收CSV文件,将文件上传到服务器,并将数据批量复制到TempHoldingTable
中。然后,代码调用一个包含Merge
语句的存储过程,将数据从TempHoldingTable
复制到相关的多个表中。我使用的是SQL Server 2008 R2。
我在存储过程中有多个Merge
语句,我只复制了下面的一个:
MERGE Client AS C
USING (SELECT ClientID, Value1, Value2, Value3, Row_Number() Over (PARTITION BY ClientID order by Date desc) as Rno
FROM TempHoldingTable) AS T ON (C.ClientID = T.ClientID)
WHEN NOT MATCHED BY TARGET AND T.Rno = 1
THEN
INSERT(ClientID, Value1, Value2, Value3)
VALUES(T.ClientID, Value1, Value2, Value3)
OUTPUT $action, inserted.*, deleted.*;
CSV文件每个月都会上传,所以假设第一个文件是在2014年1月上传的,它有以下数据:
ClientID Value1 Value2 Value3
111 abc def ghi
222 jkl mno pqr
用户随后在2014年2月上传了第二个文件,它有以下数据:
ClientID Value1 Value2 Value3
111 aaa bbb ghi
222 jkl mno pqr
333 sss ttt uuu
合并例程将更新ClientID 111的客户端表,因为值1&value2已更改,则保持ClientID 222不变,并为ClientID 333插入新行。
我的问题是,如果用户决定删除2014年2月的文件,我如何跟踪和恢复由于2014年2月份上传而引起的更改,以便客户端表包含与2014年1月上传后相同的数据。
请注意,每次上传都需要进行跟踪,这样每当用户删除文件时,数据库就会恢复到上个月的位置。
我的第二个问题是,如果ClientID存在,并且任何列的值与前一列的值不同,如何修改Merge语句以更新值。
感谢您耐心阅读本文,如有任何帮助,我们将不胜感激。
对Q1的回答:根据你的数据大小,我认为建立一个跟踪机制(Change tracking /CDC
)将是一种过度的做法(IMO)。您可能会设置一个流程(在应用文件之前),将8个表中的每一个表的数据推送到另一组表(版本数据集)中,该组表根据月份/年份存储数据。如果用户决定删除特定的月份文件,请从Versioned Dataset中提取上一个集合,并将其应用于活动表。
不过,请记住为版本化的数据集设置清除过程,否则它可能会随着时间的推移而增长。
答案Q2:您可以使用When Matched
子句
MERGE Client AS C
USING (SELECT ClientID, Value1, Value2, Value3, Row_Number() Over (PARTITION BY ClientID order by Date desc) as Rno
FROM TempHoldingTable) AS T ON (C.ClientID = T.ClientID)
WHEN NOT MATCHED BY TARGET AND T.Rno = 1
THEN
INSERT(ClientID, Value1, Value2, Value3)
VALUES(T.ClientID, Value1, Value2, Value3)
WHEN MATCHED
THEN UPDATE SET C.Value1 = T.Value1
, C.Value2 = T.Value2
, C.Value3 = T.Value#3
OUTPUT $action, inserted.*, deleted.*;