RECEIVE (Transact-SQL)
適用対象: SQL Server Azure SQL Managed Instance
キューから 1 つ以上のメッセージを受信します。 キューの保有期間の設定に応じて、キューからメッセージを削除するか、キュー内のメッセージの状態を更新します。
構文
[ 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
メッセージを受信するキューの名前です。
INTO table_variable
RECEIVE によってメッセージを格納するテーブル変数を指定します。 テーブル変数の列数は、メッセージ内の列数と同じである必要があります。 テーブル変数の各列のデータ型は、メッセージ内の対応する列のデータ型に暗黙的に変換できる必要があります。 INTO を指定しない場合、メッセージは結果セットとして返されます。
WHERE
受信するメッセージのメッセージ交換、またはメッセージ交換グループを指定します。 指定しない場合、次に使用可能なメッセージ交換グループからのメッセージが返されます。
conversation_handle = conversation_handle
受信するメッセージのメッセージ交換を指定します。 指定する conversation ハンドル は、 uniqueidentifier、または uniqueidentifierに変換できる型である必要があります。
conversation_group_id = conversation_group_id
受信するメッセージのメッセージ交換グループを指定します。 指定する conversation_group_id は、uniqueidentifer 型であるか、または uniqueidentifier に変換可能な型である必要があります。
TIMEOUT timeout
ステートメントでメッセージを待機する時間をミリ秒で指定します。 この句は 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 ステートメントでは、status
が 1
のメッセージが返されます。 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 ステートメントには、優先度のスタベーション防止はありません。 1 つの RECEIVE ステートメントによってメッセージ交換グループがロックされ、優先度の低いメッセージ交換から大量のメッセージが取得されると、そのグループ内の優先度の高いメッセージ交換からメッセージを受信できなくなります。 このような状態を回避するには、優先度の低いメッセージ交換からメッセージを取得する場合に、TOP 句を使用して、各 RECEIVE ステートメントによって取得されるメッセージ数を制限します。
キューの列
次の表は、キューの列の一覧です。
列名 | データ型 | 説明 |
---|---|---|
status |
tinyint | メッセージの状態。 RECEIVE コマンドによって返されるメッセージの場合、状態は常に 0 。 キューのメッセージには、次のいずれかの値を含めることができます。0 =Ready1 =受信したメッセージ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 =EmptyN =NoneX =XML |
message_body |
varbinary(MAX) | メッセージの内容。 |
アクセス許可
メッセージを受信するには、キューに対する RECEIVE 権限が必要です。
例
A. 会話グループ内のすべてのメッセージのすべての列を受信する
次の例では、ExpenseQueue
キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントでは、メッセージが結果セットとして返されます。
RECEIVE * FROM ExpenseQueue ;
B. 会話グループ内のすべてのメッセージに対して指定された列を受信する
次の例では、ExpenseQueue
キューから、次に使用できるメッセージ交換グループに属している使用可能なすべてのメッセージを受信します。 このステートメントでは、列 conversation_handle
、message_type_name
、message_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 ;