从队列中检索一条或多条消息。 根据队列保持设置的不同,可以从队列中删除消息或更新队列中消息的状态。
语法
[ 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
指定用于已收到的消息的会话。
提供的会话句柄必须是 uniqueidentifier,或者是可转换为 uniqueidentifier 的类型。
conversation_group_id = conversation_group_id
指定用于已收到的消息的会话组。 提供的“会话组 ID”必须是 uniqueidentifer,或属于可转换为 uniqueidentifier 的类型。
TIMEOUT timeout
指定语句等待消息的时间(以毫秒为单位)。 此子句只能与 WAITFOR 子句一起使用。 如果未指定此子句,或者超时为 -1,则等待时间不受限制。 如果超时结束,返回 RECEIVE 一个空的结果集。
注解
重要
如果该 RECEIVE 语句不是批处理或存储过程的第一个语句,前一条语句必须以分号(;) 结束。
该 RECEIVE 语句读取队列中的消息并返回结果集。 结果集由零行或多行组成,每行均包含一条消息。 如果未使用 INTO 子句,并且 column_specifier 没有为局部变量分配值,则该语句将结果集返回到调用程序。
语句返回的消息 RECEIVE 可以是不同的消息类型。 应用程序可使用 message_type_name 列将每条消息路由到用来处理关联消息类型的代码message_type_name。 有两类消息类型:
应用程序定义的消息类型,是通过使用该 CREATE MESSAGE TYPE 语句创建的。 会话中允许的应用程序定义消息类型集由为该会话指定的 Service Broker 约定定义。
返回状态信息或错误信息的 Service Broker 系统消息。
RECEIVE该语句会从队列中移除收到的消息,除非队列中明确表示消息保留。 当队列的RETENTION设置为ON时,语 RECEIVE 句会更新 status 列, 0 并将消息留在队列中。 当包含 RECEIVE 语句的事务回滚时,交易中对队列的所有更改也会被回滚,消息返回队列。
所有通过 RECEIVE 语句返回的消息都属于同一个对话组。 该 RECEIVE 语句锁定了返回消息的会话组,直到包含该语句的事务完成。 语RECEIVE句返回的status1消息是 。 语句返回 RECEIVE 的结果集合隐含顺序为:
如果来自多个对话的消息满足WHERE子句条件,该 RECEIVE 语句会返回同一对话中的所有消息,然后才返回其他对话的消息。 将按优先级降序对这些会话进行处理。
对于给定的对话,语 RECEIVE 句按升序
message_sequence_number返回消息。
该语句的 RECEIVE WHERE子句只能包含一个使用 conversation_handle 或 conversation_group_id的搜索条件。 搜索条件不能包含队列中的一个或多个其他列。
conversation_handle 或 conversation_group_id 不能是表达式。 返回的消息集取决于在 WHERE 子句中指定的条件。
如果指定 conversation_handle ,则 RECEIVE 返回指定会话中队列中可用的所有消息。
如果指定了 conversation_group_id ,则 RECEIVE 返回队列中所有来自指定会话组成员的对话中的消息。
如果没有WHERE子句,则 RECEIVE 决定了属于哪个会话群体:
在队列中具有一条或多条消息。
没有被其他 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_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 队列中下一个可用会话组的所有可用消息。 该语句将等到至少有一条消息变为可用为止,然后返回一个包含所有消息列的结果集。
WAITFOR (
RECEIVE *
FROM ExpenseQueue) ;
H. 接收消息并等待指定的间隔
下面的示例将接收 ExpenseQueue 队列中下一个可用会话组的所有可用消息。 该语句将等待 60 秒或直到至少有一条消息变为可用为止,以二者中最先发生的为准。 如果至少有一条消息可用,则该语句将返回一个包含所有消息列的结果集。 否则,该语句将返回一个空结果集。
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 ;