Лучший способ обрабатывать операторы вставки / обновления в SQL Server 2008? - PullRequest
0 голосов
/ 24 апреля 2018

Я работал над дизайном новой системы, и есть много ситуаций, когда функция будет обрабатывать операторы вставки / обновления. Обычно этот тип процесса обрабатывается старым способом с использованием языка на стороне сервера, чтобы определить, какой запрос будет выполнен. Есть несколько вещей, которые я хотел бы устранить и улучшить. Этот способ имеет много избыточного кода, где мы повторяем один и тот же код дважды для вставки и обновления. Также существует проблема в нашей старой системе, где у нас есть тонна тупиковых ошибок с сервера. Наша база данных имеет очень плохой дизайн, и это может быть также одним из многих факторов, почему у нас есть тонны этих сообщений об ошибках. Однако, работая над старым унаследованным кодом, я узнал, чего следует избегать, а не повторять одни и те же точные ошибки. Итак, вот пример кода, который обрабатывает вставку / обновление в моем текущем приложении:

<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

OR

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 beg if exists, слишком много работают в SQL, и мы должны обработать решение об обновлении вставки языком на стороне сервера. Он сказал, что предоставленное им решение предотвратит избыточность (что является правдой), а также то, что его будет эффективнее обновлять, чем вставлять данные с помощью SQL. По этой причине вставка пустой / пустой строки сэкономит некоторое время. мне интересно, по какому пути идти, и трудно решить. Если кто-то может помочь и предоставить какой-либо комментарий или пример, пожалуйста, дайте мне знать. Спасибо!

...