Reputation: 1276
I have a T-SQL query like this:
UPDATE
[MyTable]
SET
[MyField] = @myValue
WHERE
[Id] =
(
SELECT TOP(1)
[Id]
FROM
[MyTable]
WHERE
[MyField] IS NULL
-- AND other conditions on [MyTable]
ORDER BY
[Id] ASC
)
It seems that this query is not atomic (the select of 2 concurrent executions can return the same Id twice).
Edit: If I execute this query, the Id returned by the SELECT will not be available for the next execution (because [MyField] will not be NULL anymore). However, if I execute this query twice at the same time, both executions could return the same Id (and the second UPDATE would overwrite the first one).
I've read that one solution to avoid that is to use a SERIALIZABLE isolation level. Is that the best / fastest / most simple way ?
Upvotes: 0
Views: 130
Reputation: 48177
Calculate the max ID first then use it in a cross join for the the update.
WITH cte as (
SELECT TOP 1 ID
FROM [MyTable]
WHERE MYFIELD IS NULL
ORDER BY ID
)
UPDATE t
SET [ID] = cte.[ID]
FROM [MyTable] t
CROSS JOIN cte;
OUTPUT
Upvotes: 0
Reputation: 2378
This would result the top 1 value but if its the same you have the potential to return more than one value.
Try using DISTINCT
I understand that top(1) should only return 1 row but the question states its returning more than one row. So i thought it might be because the value is the same. So you could possibly use something like this
SELECT DISTINCT TOP 1 name FROM [Class];
Its either that or where clause to narrow results
Upvotes: 0