SQL 批量上传、合并和删除记录
SQL Bulk Upload, Merge and Delete records
我正在创建一个 ASP.net 网络应用程序,它从用户那里接收一个 CSV 文件,将文件上传到服务器,将数据批量复制到 TempHoldingTable
。然后代码调用包含 Merge
语句的存储过程,将数据从 TempHoldingTable
复制到相关的多个 table。我正在使用 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
Merge 例程将为 ClientID 111 更新客户端 table,因为 value1 和 value2 已更改,保持 ClientID 222 不变并为 ClientID 333 插入一个新行。
我的问题是,如果用户决定删除 2014 年 2 月的文件,我该如何跟踪和还原因 2014 年 2 月上传而导致的更改,以便客户端 table 包含与它拥有的相同的数据2014 年 1 月上传后。
请注意,每次上传都需要进行此跟踪,以便每当用户删除文件时,数据库都会恢复到与上个月相同的位置。
我的第二个问题是,如果 ClientID 存在并且任何列的值与前一列的值不同,如何修改 Merge 语句以更新值。
感谢您耐心阅读所有这些内容,如有任何帮助,我们将不胜感激。
问题 1 的答案:
根据您的数据大小,我认为设置跟踪机制 (Change tracking /CDC
) 将是一种矫枉过正 (IMO)。您可能会设置一个过程(在应用文件之前)将 8 个表中的每一个的数据推送到另一组表(版本化数据集)中,该数据集基于 month/year 存储它。
如果用户决定删除特定月份的文件,请从版本化数据集中提取前一组并将其应用于活动表。
请记住为版本化数据集设置一个清除过程,否则它会随着时间的推移变得相当大。
回答问题 2:您可以使用 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.*;
我正在创建一个 ASP.net 网络应用程序,它从用户那里接收一个 CSV 文件,将文件上传到服务器,将数据批量复制到 TempHoldingTable
。然后代码调用包含 Merge
语句的存储过程,将数据从 TempHoldingTable
复制到相关的多个 table。我正在使用 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
Merge 例程将为 ClientID 111 更新客户端 table,因为 value1 和 value2 已更改,保持 ClientID 222 不变并为 ClientID 333 插入一个新行。
我的问题是,如果用户决定删除 2014 年 2 月的文件,我该如何跟踪和还原因 2014 年 2 月上传而导致的更改,以便客户端 table 包含与它拥有的相同的数据2014 年 1 月上传后。
请注意,每次上传都需要进行此跟踪,以便每当用户删除文件时,数据库都会恢复到与上个月相同的位置。
我的第二个问题是,如果 ClientID 存在并且任何列的值与前一列的值不同,如何修改 Merge 语句以更新值。
感谢您耐心阅读所有这些内容,如有任何帮助,我们将不胜感激。
问题 1 的答案:
根据您的数据大小,我认为设置跟踪机制 (Change tracking /CDC
) 将是一种矫枉过正 (IMO)。您可能会设置一个过程(在应用文件之前)将 8 个表中的每一个的数据推送到另一组表(版本化数据集)中,该数据集基于 month/year 存储它。
如果用户决定删除特定月份的文件,请从版本化数据集中提取前一组并将其应用于活动表。
请记住为版本化数据集设置一个清除过程,否则它会随着时间的推移变得相当大。
回答问题 2:您可以使用 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.*;