我正在使用SQL Server 2017 Express来实现高性能队列(FIFO推送和弹出)-“高性能”是指我的应用程序每毫秒计数。
我最终像这样实现了队列的pop
函数:
BEGIN TRY
DECLARE @QueueID [int] = null;
--get the id of the top 1 item
SELECT TOP 1 @QueueID = [QueueID]
FROM [dbo].[ReceiverQueue] WITH (NOLOCK);
--pop that item
SELECT [QueueDateTime], [Packet], [Status]
FROM [dbo].[ReceiverQueue]
WHERE [QueueID] = @QueueID
OPTION (FAST 1);
--delete that item from the queue
DELETE FROM [dbo].[ReceiverQueue]
WHERE [QueueID] = @QueueID;
--return the popped columns
RETURN;
END TRY
BEGIN CATCH
--return exception, if pop fails
EXECUTE [dbo].[sp.GetLastError]
END CATCH;
我在StackOverflow中遇到的一些解决方案使用临时表将结果集保留在存储过程中,以备将来使用(在我的情况下,是DELETE
之后的SELECT
语句);我创建了一个简短的变体,如上所示...
尽管如此,我想知道是否存在这样的变体?
SELECT TOP 1
@QueueID = [QueueID], [QueueDateTime], [Packet], [Status]
FROM
[dbo].[ReceiverQueue] WITH (NOLOCK);
或这个?
DELETE FROM [dbo].[ReceiverQueue]
WHERE [QueueID] = SELECTED.QueueID;
尝试类似,但徒劳。
谢谢。
PS:QueueID
是IDENTITY
列
如果您具有SQL Server 2005或更高版本(如果没有,则应该升级),可以使用DELETE语句的OUTPUT子句来弹出数据,如下所示:
DELETE
FROM [dbo].[ReceiverQueue]
OUTPUT deleted.[QueueDateTime],
deleted.[Packet],
deleted.[Status]
WHERE [QueueID] = (
SELECT TOP 1 [QueueID]
FROM [dbo].[ReceiverQueue] WITH (NOLOCK)
)
如果性能问题,并且您需要ORDER BY以确保已删除的行确实是第一行,那么您可以尝试从CTE中删除
with c as (
SELECT top(1) *
FROM [dbo].[ReceiverQueue]
ORDER BY [QueueID]
)
delete from c
output deleted.[QueueDateTime],
deleted.[Packet],
deleted.[Status]
感谢你们所有人;非常感谢快速有用的回复。
结合了您的建议并创造了一个变体:
--pop top 1 row
DELETE TOP (1) FROM [dbo].[ReceiverQueue] OUTPUT DELETED.*;
--return the popped columns
RETURN;
像魅力一样工作! :)
PS。正如Serg指出的那样,排序顺序仍然很混乱。需要探讨有关这方面的this讨论...但是就目前而言,上述修订版本已经足够。