У меня есть триггер, который срабатывает после вставки. Он запускает хранимую процедуру, которая обновляет столбец IsLast
в таблице CompanyStatus
Id | CompanyId | Status | DateCreated | IsLast
Эта хранимая процедура должна установить 1
в столбце IsLast
для записи с наибольшим Id
.
CREATE PROCEDURE [dbo].[spCompanyStatusAfterInsert](@schemaName nvarchar(100), @dataTable CompanyStatus READONLY)
AS
BEGIN
DECLARE @sql nvarchar(max)
SELECT @sql = N'DECLARE
@Id bigint,
@companyId uniqueidentifier;
DECLARE CompanyStatus_Cursor CURSOR FAST_FORWARD FOR
SELECT Id, CompanyId
FROM @dataTable
OPEN CompanyStatus_Cursor
FETCH NEXT FROM CompanyStatus_Cursor
INTO @Id, @companyId
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE ' + QUOTENAME(@schemaName ) + N'.[CompanyStatus]
SET IsLast = 0
WHERE Id IN (SELECT Id
FROM ' + QUOTENAME(@schemaName) + N'.[CompanyStatus]
WHERE Id <> @Id
AND CompanyId = @companyId
AND IsLast = 1)
UPDATE ' + QUOTENAME(@schemaName) + N'.[CompanyStatus]
SET IsLast = 1
WHERE Id = @Id
FETCH NEXT FROM crs
INTO @Id, @companyId
END
CLOSE CompanyStatus_Cursor
DEALLOCATE CompanyStatus_Cursor'
EXEC sp_executesql @sql, N'@schemaName nvarchar(100), @dataTable CompanyStatus READONLY', @schemaName, @dataTable
END
(Сначала обновите все существующие IsLast
до 0
, а затем установите 1
до последнего Id
- это ожидаемое поведение).
Проблема - когда я делаю 2 вставки за очень короткое время, в результате я получаю 2 записи с IsLast = 1
.
Id | CompanyId | Status | DateCreated | IsLast
19 | 8afbd9cb-02f9-45d7-a605-a54052866bd4 | 1 | 2019-04-01 12:08:59.540 | 1
18 | 8afbd9cb-02f9-45d7-a605-a54052866bd4 | 1 | 2019-04-01 12:10:57.790 | 1
17 | fc7d1f2b-a72a-4d7f-99fa-602c72fb0410 | 2 | 2019-03-30 12:14:57.294 | 1
16 | 8afbd9cb-02f9-45d7-a605-a54052866bd4 | 1 | 2019-03-29 12:10:57.790 | 0
В примере строка с идентификатором 18
не должна быть с IsLast = 1
, поскольку есть строка с большим идентификатором.
Есть ли проблема во время выполнения этого update-запроса? (первое обновление не закончено до запуска второго).
Триггерный код:
CREATE TRIGGER [{schema}].[{schema}_TRG_CompanyStatus]
ON [{schema}].[CompanyStatus]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE @dataTable CompanyStatus
INSERT INTO @dataTable SELECT Id, CompanyId FROM inserted
EXEC [dbo].[spCompanyStatusAfterInsert] N'{schema}', @dataTable
END
GO