RECEIVE (Transact-SQL)

適用対象:SQL ServerAzure SQL Managed Instance

キューから 1 つ以上のメッセージを受信します。 キューの保有期間の設定に応じて、キューからメッセージを削除するか、キュー内のメッセージの状態を更新します。

Transact-SQL 構文表記規則

構文

[ WAITFOR ( ]  
    RECEIVE [ TOP ( n ) ]   
        <column_specifier> [ ,...n ]  
        FROM <queue>  
        [ INTO table_variable ]  
        [ WHERE {  conversation_handle = conversation_handle  
                 | conversation_group_id = conversation_group_id } ]  
[ ) ] [ , TIMEOUT timeout ]  
[ ; ]  
  
<column_specifier> ::=  
{    *   
  |  { column_name | [ ] expression } [ [ AS ] column_alias ]  
}     [ ,...n ]   
  
<queue> ::=  
{ database_name.schema_name.queue_name | schema_name.queue_name | queue_name }

引数

WAITFOR

RECEIVE文がメッセージがキューに到着するのを待つことを指定します。現在メッセージが存在しない場合に。

TOP( n )

返されるメッセージの最大数を指定します。 この句を指定しない場合、ステートメントの条件に合致したすべてのメッセージが返されます。

column_specifier

*
結果セットにキューのすべての列を含めることを指定します。

column_name
結果セットに含める列の名前です。

式 (expression)
列名、定数、関数、またはその組み合わせです。組み合わせる場合は演算子を使用します。

column_alias
結果セット内の列名を置換する別名です。

FROM

取得するメッセージが含まれているキューを指定します。

database_name
メッセージを受信するキューが含まれているデータベースの名前です。 database_name を指定しない場合、既定では現在のデータベースが使用されます。

schema_name
メッセージを受信するキューを所有するスキーマの名前です。 schema_name を指定しない場合、既定では現在のユーザーに関する既定のスキーマが使用されます。

queue_name
メッセージを受信するキューの名前です。

table_variable

メッセージを置くテーブル変数を指定 RECEIVE 。 テーブル変数の列数は、メッセージ内の列数と同じである必要があります。 テーブル変数の各列のデータ型は、メッセージ内の対応する列のデータ型に暗黙的に変換できる必要があります。 INTO を指定しない場合、メッセージは結果セットとして返されます。

WHERE

受信するメッセージのメッセージ交換、またはメッセージ交換グループを指定します。 指定しない場合、次に使用可能なメッセージ交換グループからのメッセージが返されます。

conversation_handle = conversation_handle
受信するメッセージのメッセージ交換を指定します。 指定する conversation ハンドル は、 uniqueidentifier、または uniqueidentifierに変換できる型である必要があります。

conversation_group_id = conversation_group_id
受信するメッセージのメッセージ交換グループを指定します。 指定する conversation_group_id は、uniqueidentifer 型であるか、または uniqueidentifier に変換可能な型である必要があります。

タイムアウト タイムアウト

ステートメントでメッセージを待機する時間をミリ秒で指定します。 この句は WAITFOR 句と共に使用する必要があります。 この句が指定されていない場合、またはタイムアウトが -1場合、待機時間は無制限です。 タイムアウトが終了すると、 RECEIVE は空の結果セットを返します。

注釈

重要

RECEIVE文がバッチやストアドプロシージャの最初の文でない場合、前の文はセミコロン(;)で終わらせなければなりません。

RECEIVE文はキューからメッセージを読み取り、結果セットを返します。 結果セットには 0 以上の行が含まれ、各行には 1 つのメッセージが含まれます。 INTO 句が使用されず、column_specifier でローカル変数に値が割り当てられない場合、このステートメントでは呼び出し元のプログラムに結果セットが返されます。

RECEIVE文で返されるメッセージは異なるメッセージタイプを持つことができます。 アプリケーションでは、message_type_name 列を使用して、関連付けられているメッセージ型を処理するコードに各メッセージをルーティングできます。 メッセージ型には、次の 2 種類があります。

  • CREATE MESSAGE TYPE文を用いて作成されたアプリケーション定義のメッセージタイプ。 メッセージ交換で使用できるアプリケーション定義のメッセージ型のセットは、メッセージ交換に指定されている Service Broker コントラクトで定義されます。

  • 状態やエラー情報を返す Service Broker システム メッセージ。

RECEIVE文は、キューにメッセージ保持を指定しない限り、受信したメッセージをキューから削除します。 キューのRETENTION設定がONの場合、 RECEIVE 文は status 列を 0 に更新し、メッセージはキューに残ります。 RECEIVE文を含むトランザクションがロールバックされると、そのトランザクション内のキューへのすべての変更もロールバックされ、メッセージがキューに戻されます。

RECEIVE文で返されるすべてのメッセージは、同じ会話グループに属します。 RECEIVE文は、返送されるメッセージの会話グループをロックし、その文を含むトランザクションが完了するまで続きます。 RECEIVE文は1のメッセージを返statusします。 RECEIVE文によって返される結果集合は暗黙的に順序付けられます:

  • 複数の会話からのメッセージがWHERE節の条件を満たす場合、 RECEIVE 文は他の会話のメッセージより先に1つの会話のすべてのメッセージを返します。 メッセージ交換は、優先度レベルの降順に処理されます。

  • ある会話に対して、 RECEIVE 文は昇順 message_sequence_number メッセージを返します。

RECEIVE文のWHERE節は、conversation_handleまたはconversation_group_idのいずれかを使う1つの検索条件のみを含めます。 検索条件にキューの他の列を 1 つ以上含めることはできません。 conversation_handle または conversation_group_id には、式を指定することはできません。 返されるメッセージのセットは、WHERE 句で指定した条件によって決まります。

  • conversation_handleが指定されている場合、RECEIVEは指定された会話からキュー内のすべてのメッセージを返します。

  • conversation_group_idが指定されている場合、RECEIVE指定された会話グループのメンバーである任意の会話からキュー内のすべてのメッセージを返します。

  • WHERE節がない場合、 RECEIVE どの会話グループかを決定します:

    • 1 つ以上のメッセージがキュー内にある。

    • 他の他の発言でロックされた RECEIVE はありません。

    • 上記の条件を満たすすべてのメッセージ交換グループのうち、最も高い優先度レベルを持つ。

    RECEIVE その後、選択した会話グループのメンバーである任意の会話からキュー内のすべてのメッセージを返します。

WHERE節で指定された会話ハンドルや会話グループ識別子が存在しない場合、または指定されたキューに関連付けられていない場合、 RECEIVE 文はエラーを返します。

RECEIVE文で指定されたキューのステータスがOFFに設定されている場合、その文は Transact-SQL エラーで失敗します。

WAITFOR 句を指定した場合、ステートメントは指定のタイムアウト時間が経過するか結果セットが使用可能になるまで待機します。 ステートメントが待機しているときに、キューが削除されたり、キューの状態が OFF に設定されると、ステートメントでは直ちにエラーが返されます。 RECEIVE文が会話グループまたは会話ハンドルを指定し、その会話のサービスが削除または別のキューに移動した場合、RECEIVE文は Transact-SQL エラーを報告します。

RECEIVE はユーザー定義関数では有効ではありません。

RECEIVE声明には飢餓防止の優先事項はありません。 もし単一の RECEIVE 文で会話グループがロックされ、低優先度の会話から多くのメッセージが取得された場合、グループ内の高優先度会話からはメッセージを受け取ることができません。 これを防ぐために、低優先度の会話からメッセージを取得する際には、TOP節を使って各 RECEIVE 文で取得されるメッセージ数を制限してください。

キューの列

次の表は、キューの列の一覧です。

列名 データ型 説明
status tinyint メッセージの状態。 RECEIVEコマンドで返送されたメッセージのステータスは常に0です。 キューのメッセージには、次のいずれかの値を含めることができます。

0=準備完了
1=受信したメッセージ
2=まだ完了していない
3=送信済みメッセージを保持
priority tinyint メッセージに適用されているメッセージ交換の優先度レベル。
queuing_order bigint キュー内のメッセージの順序番号。
conversation_group_id uniqueidentifier メッセージが属するメッセージ交換グループの識別子。
conversation_handle uniqueidentifier メッセージが属するメッセージ交換のハンドル。
message_sequence_number bigint メッセージ交換内でのメッセージのシーケンス番号。
service_name nvarchar(128) メッセージ交換の対象サービスの名前。
service_id int メッセージ交換の対象サービスに関する SQL Server オブジェクト識別子。
service_contract_name nvarchar(128) メッセージ交換が従うコントラクトの名前。
service_contract_id int メッセージ交換が従うコントラクトに関する SQL Server オブジェクト識別子。
message_type_name nvarchar(128) メッセージの形式を示すメッセージ型の名前。 メッセージは、アプリケーション メッセージ型か Broker システム メッセージのいずれかになります。
message_type_id int メッセージの種類を示すメッセージ型に関する SQL Server オブジェクト識別子。
validation nchar(2) メッセージに使用される検証。

E=空
N=なし
X=XML
message_body varbinary(MAX) メッセージの内容。

アクセス許可

メッセージを受け取るには、現在のユーザーがキューに対して RECEIVE 権限を持っている必要があります。

A. 会話グループ内のすべてのメッセージのすべての列を受信する

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントでは、メッセージが結果セットとして返されます。

RECEIVE * FROM ExpenseQueue ;  

B. 会話グループ内のすべてのメッセージに対して指定された列を受信する

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントでは、列 conversation_handlemessage_type_namemessage_body を含むメッセージが結果セットとして返されます。

RECEIVE conversation_handle, message_type_name, message_body  
FROM ExpenseQueue ;  

C: キューで最初に使用可能なメッセージを受信する

次の例では、ExpenseQueue キューから、最初に使用可能なメッセージを結果セットとして受信します。

RECEIVE TOP (1) * FROM ExpenseQueue ;  

D. 指定した会話のすべてのメッセージを受信する

次の例では、ExpenseQueue キューから、指定したメッセージ交換に属している使用可能なすべてのメッセージを結果セットとして受信します。

DECLARE @conversation_handle UNIQUEIDENTIFIER ;  
  
SET @conversation_handle = <retrieve conversation from database> ;  
  
RECEIVE *  
FROM ExpenseQueue  
WHERE conversation_handle = @conversation_handle ;  

E. 指定した会話グループのメッセージを受信する

次の例では、ExpenseQueue キューから、指定したメッセージ交換グループに属している使用可能なすべてのメッセージを結果セットとして受信します。

DECLARE @conversation_group_id UNIQUEIDENTIFIER ;  
  
SET @conversation_group_id =   
    <retrieve conversation group ID from database> ;  
  
RECEIVE *  
FROM ExpenseQueue  
WHERE conversation_group_id = @conversation_group_id ;  

F. テーブル変数への受信

次の例では、ExpenseQueue キューから、指定したメッセージ交換グループに属している使用可能なすべてのメッセージを受信して、テーブル変数に挿入します。

DECLARE @conversation_group_id UNIQUEIDENTIFIER ;  
  
DECLARE @procTable TABLE(  
     service_instance_id UNIQUEIDENTIFIER,  
     handle UNIQUEIDENTIFIER,  
     message_sequence_number BIGINT,  
     service_name NVARCHAR(512),  
     service_contract_name NVARCHAR(256),  
     message_type_name NVARCHAR(256),  
     validation NCHAR,  
     message_body VARBINARY(MAX)) ;  
  
SET @conversation_group_id = <retrieve conversation group ID from database> ;  
  
RECEIVE TOP (1)  
    conversation_group_id,  
    conversation_handle,  
    message_sequence_number,  
    service_name,  
    service_contract_name,  
    message_type_name,  
    validation,  
    message_body  
FROM ExpenseQueue  
INTO @procTable  
WHERE conversation_group_id = @conversation_group_id ;  

G. メッセージを受信し、無期限に待機する

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントは、少なくとも 1 つのメッセージが使用可能になるまで待機し、その後すべてのメッセージ列を含む結果セットを返します。

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue) ;  

H. メッセージの受信と指定した間隔の待機

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントは、60 秒が経過するか、少なくとも 1 つのメッセージが使用可能になるまで待機します。 少なくとも 1 つのメッセージが使用可能である場合、このステートメントはすべてのメッセージ列を含む結果セットを返します。 それ以外の場合は、空の結果セットを返します。

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue ),  
TIMEOUT 60000 ;  

I. メッセージを受信し、列の型を変更する

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 メッセージ型でメッセージに XML ドキュメントが含まれることが指定されている場合、このステートメントでは、メッセージ本文が XML に変換されます。

WAITFOR (  
    RECEIVE message_type_name,  
        CASE  
            WHEN validation = 'X' THEN CAST(message_body as XML)  
            ELSE NULL  
         END AS message_body   
         FROM ExpenseQueue ),  
TIMEOUT 60000 ;  

J. メッセージの受信、メッセージ本文からのデータの抽出、会話状態の取得

次の例では、ExpenseQueue キューから、次に使用できるメッセージ交換グループに属している、次に使用可能なメッセージを取得します。 メッセージの型が //Adventure-Works.com/Expenses/SubmitExpense の場合、このステートメントでは、メッセージ本文から従業員 ID とアイテム一覧が抽出されます。 また、このステートメントでは ConversationState テーブルからメッセージ交換の状態も取得されます。

WAITFOR(  
    RECEIVE   
    TOP(1)  
      message_type_name,  
      COALESCE(  
           (SELECT TOP(1) ConversationState  
            FROM CurrentConversations AS cc  
            WHERE cc.ConversationHandle = conversation_handle),  
           'NEW')  
      AS ConversationState,  
      COALESCE(  
          (SELECT TOP(1) ErrorCount  
           FROM CurrentConversations AS cc  
           WHERE cc.ConversationHandle = conversation_handle),   
           0)  
      AS ConversationErrors,  
      CASE WHEN message_type_name = N'//Adventure-Works.com/Expenses/SubmitExpense'  
          THEN CAST(message_body AS XML).value(  
                'declare namespace rpt = "https://Adventure-Works.com/schemas/expenseReport"  
                   (/rpt:ExpenseReport/rpt:EmployeeID)[1]', 'nvarchar(20)')  
         ELSE NULL  
      END AS EmployeeID,  
      CASE WHEN message_type_name = N'//Adventure-Works.com/Expenses/SubmitExpense'  
          THEN CAST(message_body AS XML).query(  
                'declare namespace rpt = "https://Adventure-Works.com/schemas/expenseReport"   
                     /rpt:ExpenseReport/rpt:ItemDetail')  
          ELSE NULL  
      END AS ItemList  
    FROM ExpenseQueue   
), TIMEOUT 60000 ;