This one will take some explaining. What I\'ve done is create a specific custom message queue in SQL Server 2005. I have a table with messages that contain timestamps for both a
This seems like the kind of situation where OUTPUT can be useful:
-- Acknowledge and grab the next message
declare @message table (
-- ...your `ActionMessages` columns here...
)
update ActionMessages
set AcknowledgedTime = getdate()
output INSERTED.* into @message
where ActionMessageId in (select top(1) ActionMessageId from UnacknowledgedDemands)
and AcknowledgedTime is null
-- Use the data in @message, which will have zero or one rows assuming
-- `ActionMessageId` uniquely identifies a row (strongly implied in your question)
...
...
There, we update and grab the row in the same operation, which tells the query optimizer exactly what we're doing, allowing it to choose the most granular lock it can and maintain it for the briefest possible time. (Although the column prefix is INSERTED
, OUTPUT
is like triggers, expressed in terms of the UPDATE
being like deleting the row and inserting the new one.)
I'd need more information about your ActionMessages
and UnacknowledgedDemands
tables (views/TVFs/whatever), not to mention a greater knowledge of SQL Server's automatic locking, to say whether that and AcknowledgedTime is null
clause is necessary. It's there to defend against a race condition between the sub-select and the update. I'm certain it wouldn't be necessary if we were selecting from ActionMessages
itself (e.g., where AcknowledgedTime is null
with a top
on the update
, instead of the sub-select on UnacknowledgedDemands
). I expect even if it's unnecessary, it's harmless.
Note that OUTPUT
is in SQL Server 2005 and above. That's what you said you were using, but if compatibility with geriatric SQL Server 2000 installs were required, you'd want to go another way.