Я работал над дизайном новой системы, и есть много ситуаций, когда функция будет обрабатывать операторы вставки / обновления. Обычно этот тип процесса обрабатывается старым способом с использованием языка на стороне сервера, чтобы определить, какой запрос будет выполнен. Есть несколько вещей, которые я хотел бы устранить и улучшить. Этот способ имеет много избыточного кода, где мы повторяем один и тот же код дважды для вставки и обновления. Также существует проблема в нашей старой системе, где у нас есть тонна тупиковых ошибок с сервера. Наша база данных имеет очень плохой дизайн, и это может быть также одним из многих факторов, почему у нас есть тонны этих сообщений об ошибках. Однако, работая над старым унаследованным кодом, я узнал, чего следует избегать, а не повторять одни и те же точные ошибки. Итак, вот пример кода, который обрабатывает вставку / обновление в моем текущем приложении:
<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. По этой причине вставка пустой / пустой строки сэкономит некоторое время. мне интересно, по какому пути идти, и трудно решить. Если кто-то может помочь и предоставить какой-либо комментарий или пример, пожалуйста, дайте мне знать. Спасибо!