If you want exactly one task with static = active, then tune the table to make sure it is true. Use filtered unique index:
create unique index unq_tasks_status_filter_active on tasks(status) where status = 'Active';
The second parallel update may fail, but you will be sure of uniqueness. Application code can handle such failed updates and try again.
Using real update plans can be dangerous. This is why it is safer to have such a database. Key implementation details may vary by environment and version of SQL Server. For example, what works in a single-threaded single-processor environment may not work in a parallel environment. What works with one isolation level may not work with another.
EDIT:
And I can not resist. To improve performance, consider writing a query as:
UPDATE Tasks SET Status = 'Active' WHERE NOT EXISTS (SELECT 1 FROM Tasks WHERE Status = 'Active' ) AND Id = (SELECT TOP 1 Id FROM Tasks WHERE Type = 2
Then place the indexes on Tasks(Status) and Tasks(Type, Id) . In fact, with the right request, you may find that the request is so fast (despite updating the index) that your concern about current updates is greatly alleviated. This would not solve the state of the race, but it could at least make it rare.
And if you commit errors, then using a unique filtered index, you can simply do:
UPDATE Tasks SET Status = 'Active' WHERE Id = (SELECT TOP 1 Id FROM Tasks WHERE Type = 2
This will result in an error if the row is already active.
Note. All of these queries and concepts can be applied to "one active for each group." This answer solves the question you asked. If you have a โone active for each groupโ problem, try asking another question.
Gordon linoff
source share