Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да внедрим условна съхранена процедура Upsert?

Събрах следния скрипт, за да докажа този трик, който използвах преди години. Ако го използвате, ще трябва да го промените, за да отговаря на вашите цели. Следват коментари:

/*
CREATE TABLE Item
 (
   Title      varchar(255)  not null
  ,Teaser     varchar(255)  not null
  ,ContentId  varchar(30)  not null
  ,RowLocked  bit  not null
)


UPDATE item
 set RowLocked = 1
 where ContentId = 'Test01'

*/


DECLARE
  @Check varchar(30)
 ,@pContentID varchar(30)
 ,@pTitle varchar(255)
 ,@pTeaser varchar(255)

set @pContentID = 'Test01'
set @pTitle     = 'TestingTitle'
set @pTeaser    = 'TestingTeasier'

set @check = null

UPDATE dbo.Item
 set
   @Check = ContentId
  ,Title  = @pTitle
  ,Teaser = @pTeaser
 where ContentID = @pContentID
  and RowLocked = 0

print isnull(@check, '<check is null>')

IF @Check is null
    INSERT dbo.Item (ContentID, Title, Teaser, RowLocked)
     values (@pContentID, @pTitle, @pTeaser, 0)

select * from Item

Номерът тук е, че можете да зададете стойности в локални променливи в оператор Update. По-горе стойността на "флаг" се задава само ако актуализацията работи (т.е. критериите за актуализация са изпълнени); в противен случай няма да се промени (тук, оставен на нула), можете да проверите за това и да обработите съответно.

Що се отнася до транзакцията и превръщането й в сериализираема, бих искал да знам повече за това какво трябва да бъде капсулирано в транзакцията, преди да предложа как да продължа.

-- Допълнение, продължение на втория коментар по-долу ------------

Идеите на г-н Saffron са задълбочен и солиден начин за внедряване на тази рутина, тъй като вашите първични ключове се дефинират отвън и се предават в базата данни (т.е. не използвате колони за самоличност - добре от мен, те често се използват прекалено много).

Направих още няколко теста (добавих ограничение за първичен ключ към колона ContentId, обвих UPDATE и INSERT в транзакция, добавих подсказката за сериализиране към актуализацията) и да, това трябва да направи всичко, което искате. Неуспешната актуализация задейства заключване на диапазон на тази част от индекса и това ще блокира всички едновременни опити за вмъкване на тази нова стойност в колоната. Разбира се, ако N заявки са изпратени едновременно, "първият" ще създаде реда и той ще бъде незабавно актуализиран от втория, третия и т.н. - освен ако не зададете "заключването" някъде по реда. Добър трик!

(Имайте предвид, че без индекса в ключовата колона бихте заключили цялата таблица. Освен това заключването на диапазона може да заключи редовете от „двете страни“ на новата стойност – или може би няма да го направят, аз не тествайте това. Не би трябвало да има значение, тъй като продължителността на операцията трябва [?] да бъде в едноцифрени милисекунди.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да изчистя SqlDependency от паметта на SQL Server?

  2. Как да създадете уникален индекс на колона NULL?

  3. Създайте правило за ограничаване на специални знаци в таблицата в sql сървъра

  4. Шифроване на таблици на база данни в SQL Server 2008

  5. Тип данни за съхраняване на IP адрес в SQL Server