2017-01-14 2 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)を取得するために、私はそれに1列、INSERT行でテーブル変数を作成する必要があり、その後、すぐにSELECT同じ行でる。アトミック性を損なわないEXEC jobs.DequeueJobを呼び出すと、deleted.JobIDをキャプチャするより良い方法がありますか(可読性または最適化の観点から)

EXEC @JobID = jobs.DequeueJobは有効な構文であり、有望ですが、OUTPUTの値ではなく戻り値を取得します。 This answerにはいくつかの結果渡しオプションの良い議論がありますが、私の状況をそれらのいずれかに適合させる方法を見つけることはできません。

私はSQL Server 2012 SP3を使用していますが、これより新しい構文でこの構文が改善されている場合は、アップグレードする準備が整いました。

+0

私の考えでは、@tablevariableにdeleted.idを出力するよりも良い方法はありません –

答えて

1

私はShakeer Mirzaのコメントに同意します.OUTPUT句の結果をテーブルに挿入することは、T-SQLで値を使用できる唯一の方法なので避けられません。別々のprocsの特定の理由がある場合を除いて、あなたは以下の例のようにリファクタリングすることができます。これはわずかに臭いの少ないIMHOです。そうDELETE TOPとは定義された順序がないことを

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 

注あなたはFIFOが必要な場合は、DELETEORDER BYでサブクエリを使用することを検討してください。

関連する問題