Я пытаюсь написать некоторый SQL, который выполняет переход по довольно сложным критериям:
BEGIN TRAN;
UPDATE LocationLog WITH(SERIALIZABLE)
SET StartTime = CASE
WHEN StartTime > @StartTime THEN @StartTime
ELSE StartTime
END,
EndTime = CASE
WHEN EndTime < @EndTime THEN @EndTime
ELSE EndTime
END,
Updated = GETUTCDATE()
WHERE Who = @Who
AND (
StartTime BETWEEN @RangeStart and @RangeEnd
or
EndTime BETWEEN @RangeStart and @RangeEnd
)
AND cast(Latitude as decimal(8,5)) = cast(@Latitude as decimal(8, 5))
AND cast(Longitude as decimal(8,5)) = cast(@Longitude as decimal(8, 5))
AND (Accuracy = @Accuracy or COALESCE(Accuracy, @Accuracy) is NULL)
AND (Altitude = @Altitude or COALESCE(Altitude, @Altitude) is NULL)
AND (AltitudeAccuracy = @AltitudeAccuracy or COALESCE(AltitudeAccuracy, @AltitudeAccuracy) is NULL)
AND (Heading = @Heading or COALESCE(Heading, @Heading) is NULL)
AND (Speed = @Speed or COALESCE(Speed, @Speed) is NULL);
IF @@ROWCOUNT = 0
BEGIN
INSERT Position(UUID, Who, StartTime, EndTime, Latitude, Longitude, Accuracy, Altitude, AltitudeAccuracy, Heading, Speed, CreatedTime, Updated)
VALUES (NEWID(), @Who, @StartTime, @EndTime, @Latitude, @Longitude, @Accuracy, @Altitude, @AltitudeAccuracy, @Heading, @Speed, GETUTCDATE(), GETUTCDATE())
END
COMMIT TRAN
Я использую стандартное «обновление, если @@ rowcount = 0 insert» с транзакциейи сериализуемый, который (насколько я могу судить) такой же, как и Блог Сэма Шафрона «Шаблон вставки или обновления для сервера Sql» , за исключением того, что вместо одного идентификатора столбца я использую большойнабор столбцов-кандидатов, поскольку нет способа программно создать единственный ключ-кандидат.
Я захожу в тупик, когда он вызывается одновременно, и я не могу понять, почему.Просто, чтобы помочь завершить картину, вот определение таблицы:
CREATE TABLE LocationLog (
[UUID] [uniqueidentifier] NOT NULL CONSTRAINT [PK_Position] PRIMARY KEY NONCLUSTERED ,
[Who] [uniqueidentifier] NOT NULL INDEX [IX_Who],
[StartTime] [datetime] NOT NULL,
[EndTime] [datetime] NULL,
[Latitude] [decimal](9, 6) NOT NULL,
[Longitude] [decimal](9, 6) NOT NULL,
[Accuracy] [float] NULL,
[Altitude] [float] NULL,
[AltitudeAccuracy] [float] NULL,
[Heading] [float] NULL,
[Speed] [float] NULL,
[CreatedUtc] [datetime] NOT NULL,
[UpdatedUtc] [datetime] NOT NULL
)
А вот скрипт, который вызовет много взаимоблокировок с использованием вышеуказанного sql: https://dotnetfiddle.net/xkze6l
Я надеюсь на две вещи в ответе:
- Объяснение того, почему это заходит в тупик.(Я прошелся по коду и не понимаю, в чем я ошибся).
- Исправление для кода, которое позволит мне сделать это.