2017-01-14 65 views
0

我使用一個表作爲高併發條件下FIFO queue,並自動出列如下:從EXEC stored_procedure中捕獲OUTPUT deleted.x的正確方法是什麼?

CREATE PROCEDURE [jobs].[DequeueJob]   
AS 
BEGIN 
    DELETE TOP(1) 
    FROM jobs.JobQueue WITH (ROWLOCK, READPAST) 
    OUTPUT deleted.JobID; 
END 

我從另一個調用這個存儲過程來捕獲和使用deleted.JobID,所以我有這樣的:

CREATE PROCEDURE [jobs].[GetJob]   
AS 
BEGIN 
    DECLARE @Job TABLE (JobID int)  

    INSERT @Job EXEC jobs.DequeueJob  

    DECLARE @JobID int 
    SET @JobID = (SELECT JobID from @Job) 

    UPDATE jobs.Jobs 
    SET IsInQueue = 0 
    WHERE JobID = @JobID 

    SELECT * 
    FROM jobs.Jobs 
    WHERE JobID = @JobID 
END 

這工作得很好,但它的氣味:得到的值(JobID),我想用,我必須有一列,INSERT行創建一個表變量進去,然後立即SELECT同一行回出。當我打電話給EXEC jobs.DequeueJob時,有沒有更好的方法(從可讀性或優化的角度來看)捕獲deleted.JobID,這不會破壞它的原子性?

EXEC @JobID = jobs.DequeueJob是有效的語法,看起來很有希望,但它捕獲返回值,而不是OUTPUT值。 This answer對幾個結果傳遞選項有很好的討論,但我找不到適合我的情況的方法。

我正在使用SQL Server 2012 SP3,但我準備升級,如果在較新版本中可以使用此改進語法。

+0

在我的想法中,沒有比輸出deleted.id變爲@tablevariable更好的方法了 –

回答

1

我同意Shakeer Mirza的評論,即將OUTPUT子句結果插入到表中是不可避免的,因爲這是在T-SQL中可以使用該值的唯一方法。除非,你有獨立的特效的具體原因,你可以重構像下面的例子,這是稍微少臭,恕我直言。

CREATE PROCEDURE [jobs].[GetNextJob]   
AS 

DECLARE @Job TABLE (JobID int PRIMARY KEY); 

DELETE TOP(1) FROM jobs.JobQueue WITH (ROWLOCK, READPAST) 
OUTPUT deleted.JobID INTO @Job(JobID); 

UPDATE jobs.Jobs set IsInQueue = 0 
OUTPUT inserted.* 
WHERE JobID = (SELECT JobID from @Job); 
GO 

注意,沒有定義以便與DELETE TOP因此,如果您需要FIFO,考慮在DELETE使用子查詢與ORDER BY

相關問題