Исходный код вики INSERT or UPDATE

Редактировал(а) Alexandr Fokin 2023/12/16 14:11

Скрыть последних авторов
Alexandr Fokin 6.1 1 Solutions for INSERT OR UPDATE on SQL Server
2 https://stackoverflow.com/questions/108403/solutions-for-insert-or-update-on-sql-server
3
4
Alexandr Fokin 7.1 5 1)
6
Alexandr Fokin 2.1 7 {{code language="sql"}}
Alexandr Fokin 3.1 8 DECLARE @key INT = 12
9 DECLARE @msg NVARCHAR(MAX) = 'L2'
Alexandr Fokin 2.1 10
Alexandr Fokin 3.1 11 BEGIN TRAN
12 IF EXISTS (
13 SELECT *
14 FROM DBO.LOG2ENTITY WITH (UPDLOCK, SERIALIZABLE)
15 WHERE ID = @key
Alexandr Fokin 2.1 16 )
Alexandr Fokin 3.1 17 BEGIN
18 UPDATE DBO.LOG2ENTITY
19 SET
Alexandr Fokin 4.1 20 Message = @msg
Alexandr Fokin 3.1 21 WHERE ID =@key
22 END
23 ELSE
24 BEGIN
Alexandr Fokin 4.1 25 INSERT INTO DBO.LOG2ENTITY (Message)
Alexandr Fokin 3.1 26 VALUES (@msg)
27 END
28 COMMIT TRAN
Alexandr Fokin 5.1 29
Alexandr Fokin 2.1 30 {{/code}}
Alexandr Fokin 7.1 31
32
33 2) Идея-костыль:
34 2.1) Если строка отсутствует в таблице (EXSIST SELECT)
35 (Опционально возможен сразу UPDLOCK),
36 то пробуем выполнить вставку строки, в случае возникновения ошибки, что ключ уже существует, игнорируем ее.
37 (При этом возможно, что вместо большей части данных пока что подставляем значения по умолчанию, важен только ключ)
38 2.2) Явно начинаем транзакцию
39 2.2.1) Извлекаем строку с блокировкой (WITH UPDLOCK). К данному этапу строка уже гарантированно есть в БД (Если не рассматривать удаление).
40 2.2.2) При необходимости проверяем состояние строки. Обеспечивая идемпотентность и корректность с точки зрения многопоточности и версионности.
41 2.2.3) При необходимости обновляем строку.