Исходный код вики INSERT or UPDATE
Редактировал(а) Alexandr Fokin 2023/12/16 14:11
Последние авторы
author | version | line-number | content |
---|---|---|---|
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 | |||
5 | 1) | ||
6 | |||
7 | {{code language="sql"}} | ||
8 | DECLARE @key INT = 12 | ||
9 | DECLARE @msg NVARCHAR(MAX) = 'L2' | ||
10 | |||
11 | BEGIN TRAN | ||
12 | IF EXISTS ( | ||
13 | SELECT * | ||
14 | FROM DBO.LOG2ENTITY WITH (UPDLOCK, SERIALIZABLE) | ||
15 | WHERE ID = @key | ||
16 | ) | ||
17 | BEGIN | ||
18 | UPDATE DBO.LOG2ENTITY | ||
19 | SET | ||
20 | Message = @msg | ||
21 | WHERE ID =@key | ||
22 | END | ||
23 | ELSE | ||
24 | BEGIN | ||
25 | INSERT INTO DBO.LOG2ENTITY (Message) | ||
26 | VALUES (@msg) | ||
27 | END | ||
28 | COMMIT TRAN | ||
29 | |||
30 | {{/code}} | ||
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) При необходимости обновляем строку. |