首页 > 解决方案 > 在 SQL Server 2008 中处理插入/更新语句的最佳方法?

问题描述

我一直致力于新系统的设计,在很多情况下函数将处理插入/更新语句。通常这种过程是使用服务器端语言以旧方式处理的,以确定将执行哪个查询。我想消除和改进的东西很少。这种方式有很多冗余代码,我们为插入和更新重复两次相同的代码。在我们的旧系统中也存在一个问题,我们有大量来自服务器的死锁错误。我们的数据库设计非常糟糕,这可能也是我们有大量错误消息的众多因素之一。然而,在处理旧的遗留代码时,我已经学会了应该避免什么,而不是重复同样的错误。所以这里是在我当前的应用程序中处理插入/更新的代码示例:

<cfif len(FORM.frm_id)>
    <cfquery name="updateTbl" datasource="#dns#">
        UPDATE Table1
        SET
            testdt = <cfqueryparam value="#FORM.frm_testdt#" cfsqltype="cf_sql_date" maxlength="10" null="#!len(FORM.frm_testdt)#" />,
            location = <cfqueryparam value="#trim(FORM.frm_location)#" cfsqltype="cf_sql_varchar" maxlength="500" null="#!len(trim(FORM.frmhs_location))#" />,
            testwhy = <cfqueryparam value="#trim(FORM.frm_testwhy)#" cfsqltype="cf_sql_varchar" maxlength="50" null="#!len(trim(FORM.frm_testwhy))#" />
       WHERE id = <cfqueryparam value="#FORM.frm_id#" cfsqltype="cf_sql_integer" />
    </cfquery>
<cfelse>
    <cfquery name="insertTbl" datasource="#dns#">
       INSERT INTO Table1(
          testdt, location, testwhy
       )VALUES(
          <cfqueryparam value="#FORM.frm_testdt#" cfsqltype="cf_sql_date" maxlength="10" null="#!len(FORM.frm_testdt)#" />,
          <cfqueryparam value="#trim(FORM.frm_location)#" cfsqltype="cf_sql_varchar" maxlength="500" null="#!len(trim(FORM.frmhs_location))#" />,
          <cfqueryparam value="#trim(FORM.frm_testwhy)#" cfsqltype="cf_sql_varchar" maxlength="50" null="#!len(trim(FORM.frm_testwhy))#" />
       ) 
       SELECT SCOPE_IDENTITY() AS RecID 
    </cfquery>
</cfif>

正如您在上面的示例中看到的那样,有很多冗余,但同时我不确定它是否有效。也可能是死锁经常发生的原因。所以我做了一些研究,下面是一些人建议的例子:

To avoid deadlocks and PK violations you can use something like this:

begin tran
if exists (select * from table with (updlock,serializable) where key = @key)
begin
   update table set ...
   where key = @key
end
else
begin
   insert into table (key, ...)
   values (@key, ...)
end
commit tran

或者

begin tran
   update table with (serializable) set ...
   where key = @key

   if @@rowcount = 0
   begin
      insert into table (key, ...) values (@key,..)
   end
commit tran

我不确定这两个示例是否是好的做法,以及这两个解决方案是否有任何优点或缺点。然后我和其中一位高级程序员交谈过,他们提出了下一个建议。

-First use server side language (ColdFusion in our case) to determine if process is Insert or Update. 
-Then if it's insert do insert in the table with the blank data row.
-Run update and populate data. 

在他看来,我上面用 SQL 展示的两个示例在 SQLbeg if exists中投入了太多工作,我们应该通过服务器端语言处理插入更新的决定。他说他提供的解决方案将防止冗余(这是真的),而且更新比使用 SQL 插入数据更有效。出于这个原因,插入空/空白行将节省一些时间。我想知道该走哪条路,很难决定。如果有人可以提供帮助并提供一些评论或示例,请告诉我。谢谢!

标签: sql-serversql-server-2008sql-updatedeadlocksql-insert

解决方案


推荐阅读