根据经验,我倾向于编写 Upsert 程序.......但我将“匹配”基于 unique_constraint,而不是代理键。
例如。
dbo.Employee EmployeeUUID 是PK,Surrogate Key SSN 是唯一约束。
dbo.uspEmployeeUpsert would look something like this:
Insert into dbo.Employee (EmployeeUUID , LastName , FirstName, SSN )
Select NEWID() , LastName , FirstName , SSN
from @SomeHolderTable holder
where not exists (select null from dbo.Employee innerRealTable where
innerRealTable.SSN = holder.SSN )
Update dbo.Employee
Set EmployeeUUID = holder.EmployeeUUID
, LastName = ISNULL ( holder.LastName , e.LastName ) /* or COALESCE */
, FirstName = COALESCE ( holder.FirstName , e.FirstName )
from dbo.Employee e , @SomeHolderTable holder
Where e.SSN = holder.SSN
您还可以使用 MERGE 功能。
您还可以将 SSN 替换为 SurrogateKey(在本例中为 EmployeeUUID)
你问什么@SomeHolderTable?
我喜欢将 xml 传递给存储过程,将其分解为 @Variable 或 #Temp 表,然后为 CU 编写逻辑。D(elete) 也是可能的,但我通常隔离到一个单独的程序。
为什么我要这样做?
因为我可以用一个 db hit 更新 1 或 100 或 1000 或 N 条记录。我的逻辑很少改变,并且被孤立在一个地方。
现在,粉碎 Xml 对性能有一点影响。但我发现它在 99% 的情况下都是可以接受的。每隔一段时间,我都会编写一个非“基于集合”的 Upsert 例程。但这是针对重击使用的重击程序。
这是我的看法。
您可以在本文中看到这种方法的“基于集合”部分(使用旧的 OPENXML 语法):
http://msdn.microsoft.com/en-us/library/ff647768.aspx
找到短语:“使用 OpenXML 执行批量更新和插入”
以下是上述 URL 所讨论内容的“更多代码”版本:
http://support.microsoft.com/kb/315968
编辑
if exists ( select 1 from dbo.Employee e where e.SSN = holder.SSN )
BEGIN
Insert into dbo.Employee (EmployeeUUID , LastName , FirstName, SSN )
Select NEWID() , LastName , FirstName , SSN
from @SomeHolderTable holder
where not exists (select null from dbo.Employee innerRealTable where
innerRealTable.SSN = holder.SSN )
END
我不一定会这样做。但如果您想要“布尔检查”,它是一个选项。
因此,通过我的 uniqueidentifier 设置,当我知道我有一个新项目时,我会将“空 Guid”(00000000-0000-0000-0000-000000000000)(C# 中的 Guid.Empty)传递给该过程。这将是我在您的场景中的“-1”检查。
这是一种方法,您可以检查“如果存在”。
这有点取决于你在底池中有多少手牌。
另外,我没有提到当我在底池中有很多手时,我会切碎 xml .....然后我会围绕我的 CU 语句执行 BEGIN TRAN 和 COMMIT TRAN(其中 ROLLBACK 为出色地)。这样我的 CU 就是原子的,全有或全无。
MERGE 函数也将执行此操作。但是 MERGE 的优缺点是另一个话题。