如何在存储过程中删除SQL Server中的选定列

问题描述 投票:0回答:3

我正在使用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:QueueIDIDENTITY

sql sql-server database queue sql-execution-plan
3个回答
1
投票

如果您具有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)
    )

1
投票

如果性能问题,并且您需要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] 

0
投票

感谢你们所有人;非常感谢快速有用的回复。

结合了您的建议并创造了一个变体:

    --pop top 1 row
    DELETE TOP (1) FROM [dbo].[ReceiverQueue] OUTPUT DELETED.*;
    --return the popped columns 
    RETURN;

像魅力一样工作! :)

PS。正如Serg指出的那样,排序顺序仍然很混乱。需要探讨有关这方面的this讨论...但是就目前而言,上述修订版本已经足够。

© www.soinside.com 2019 - 2024. All rights reserved.