【问题标题】:Modify SQL result set before returning from stored procedure从存储过程返回之前修改 SQL 结果集
【发布时间】:2010-02-24 23:56:56
【问题描述】:

我的 SQL Server 2008 DB 中有一个简单的表:

Tasks_Table
-id
-task_complete
-task_active
-column_1
-..
-column_N

该表存储必须由服务执行的未完成任务的指令。

我希望将来能够扩展我的系统。到目前为止,只有 1 台计算机上的 1 个服务从表中读取。我有一个存储过程,它选择所有未完成和非活动的任务。当服务开始处理任务时,它会更新所有返回行中的 task_active 标志。

要启用系统扩展,我想在更多机器上启用服务部署。因为我想防止将一个任务返回给多个服务,所以我必须更新返回未完成和非活动任务的存储过程。

我认为我必须锁定表(一次只有 1 个读取器 - 我知道我必须使用适当的 ISOLATION LEVEL),并在返回结果集之前更新结果集每一行中的 task_active 标志。

所以我的问题是如何在返回之前修改存储过程中的SELECT结果集?

【问题讨论】:

    标签: sql-server tsql sql-server-2008 stored-procedures


    【解决方案1】:

    这是典型的出队模式,使用 OUTPUT 子句实现,并在 MSDN 中进行了描述,请参阅 OUTPUT Clause (Transact-SQL) 中的队列段落:

    UPDATE TOP(1) Tasks_Table WITH (ROWLOCK, READPAST)
     SET task_active = 1
     OUTPUT INSERTED.id,INSERTED.column_1, ...,INSERTED.column_N 
     WHERE task_active = 0;
    

    ROWLOCK,READPAST 提示允许高吞吐量和高并发:多个线程/处理可以使新任务入队,而多个线程/处理出队任务。没有订单保证。

    更新

    如果您想订购结果,您可以使用 CTE:

    WITH cte AS (
      SELECT TOP(1) id, task_active, column_1, ..., column_N
      FROM Task_Table WITH (ROWLOCK, READPAST)
      WHERE task_active = 0
      ORDER BY <order by criteria>)
    UPDATE cte
      SET task_active = 1
    OUTPUT INSERTED.id, INSERTED.column_1, ..., INSERTED.column_N;
    

    我在文章 Using Tables as Queues 中讨论了这个和其他入队/出队技术。

    【讨论】:

    • 有没有办法在调用 TOP(1) 之前订购 Task_Table 而不会丢失 ROWLOCK 和 READPAST?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    • 2011-08-10
    • 2011-03-20
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多