2

我知道使用 CRUD 的好处,也有一些缺点,但我想获得更多专家的反馈和建议,了解以下将数据写入数据库的过程,特别是关于最佳实践和可能的优缺点。

作为开发人员,我遇到了两种创建记录的基本方法。第一个(在我见过的大多数作品中通常是最没有帮助的)是创建一个存根并在需要的地方使用各种填充字段(包括 PK)。这通常会导致大量不被认可的记录在数据库中漂浮,没有真正的目的。

第二种方法是只在内存中保存一个存根,给(什么是)对象的 PK 字段一个默认值,例如,-1代表一个新记录。这将数据库访问保持在最低限度,尤其是在以后不需要记录的情况下。

就个人而言,我发现第二种方式比第一种方式更加宽容和直接。不过,我想提出的问题是,是否排除 CRUD 以支持基于上述默认值执行 CRUD 过程的各个方面的存储过程,例如INSERT......UPDATE

BEGIN
    IF @record_id = -1 
        INSERT ....
    ELSE
        UPDATE ....
END 

对于任何反馈,我们都表示感谢。

4

1 回答 1

1

根据经验,我倾向于编写 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 的优缺点是另一个话题。

于 2013-09-12T13:46:52.960 回答