RECEIVE (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 ]
| column_alias = expression
} [ ,...n ]
<queue> ::=
{
[ database_name . [ schema_name ] . | schema_name . ]
queue_name
}
参数
- WAITFOR
指定如果当前没有消息,则 RECEIVE 语句将等待消息到达队列。
- TOP( n )
指定要返回的最大消息数。 如果未指定该子句,则返回所有满足语句条件的消息。
- *
指定结果集包含队列中的所有列。
- column_name
要包含在结果集中的列的名称。
- expression
列名、常量、函数或由运算符连接的列名、常量和函数的任意组合。
- column_alias
替换结果集内列名的可选名。
- FROM
指定包含要检索的消息的队列。
- database_name
包含从中接收消息的队列的数据库的名称。 如果未提供 database_name,则默认为当前数据库。
- schema_name
从中接收消息的队列所属架构的名称。 如果未提供 schema_name,则默认为当前用户的默认架构。
- queue_name
从中接收消息的队列的名称。
- INTO table_variable
指定从已收到的消息选到列的表。
- WHERE
指定用于已收到的消息的会话或会话组。 如果省略,则从下一个可用会话组返回消息。
- conversation_handle = conversation_handle
指定用于已收到的消息的会话。 提供的 conversation_handle 的数据类型必须为 uniqueidentifer 或可转换为 uniqueidentifier 的类型。
- conversation_group_id = conversation_group_id
指定用于已收到的消息的会话组。 提供的 conversation_group_id 的数据类型必须为 uniqueidentifier 或可转换为 uniqueidentifier 的类型。
- TIMEOUT timeout
指定语句等待消息的时间(以毫秒为单位)。 该子句只能与 WAITFOR 子句一起使用。 如果未指定该子句,或者超时值为 -1,则等待时间没有限制。 如果超时时间已到,则 RECEIVE 返回一个空结果集。
备注
重要提示: |
---|
如果 RECEIVE 语句不是批处理或存储过程中的第一条语句,则前面的语句必须以 Transact-SQL 语句终止符分号 (;) 终止。 |
RECEIVE 语句将从队列读取消息并返回结果集。 返回的结果集包含零行或多行,每行包含一个消息。 如果未使用 INTO 子句,并且 column_specifier 没有为局部变量分配值,则该语句将结果集返回到调用程序。
RECEIVE 语句将从队列中删除已收到的消息,但队列指定消息保持时除外。 当队列的 RETENTION 设置为 ON 时,RECEIVE 语句将 status 列更新为 1,并使消息留在队列中。 当包含 RECEIVE 语句的事务回滚时,该事务中队列的所有更改也会随之回滚,并将消息返回到队列。
RECEIVE 语句返回的所有消息都属于同一个会话组。 RECEIVE 语句将锁定返回的消息所属的会话组,直到包含该语句的事务完成为止。 将 RECEIVE 语句返回的结果集进行隐式排序。 对于给定的会话,RECEIVE 语句将返回 status 为 1 的消息,并将消息按 message_sequence_number 的升序排列。
RECEIVE 语句的 WHERE 子句可能只包含使用 conversation_handle 或 conversation_group_id 的搜索条件。 搜索条件不能包含队列中的任何其他列。 conversation_handle 或 conversation_group_id 不能为表达式。 如果未指定 WHERE 子句,则 RECEIVE 语句将从下一个可用会话组返回消息,而不考虑当前连接在其他会话组上持有的锁。 当 WHERE 子句未指定 conversation_handle 时,RECEIVE 语句将从会话组返回消息,而不考虑每个消息所属的会话。 如果 WHERE 子句中指定的会话句柄或会话组标识符不存在,或者未与指定的队列关联,则 RECEIVE 语句将返回一个错误。
如果 RECEIVE 语句指定的队列的队列状态设置为 OFF,则该语句将失败,并返回一个 Transact-SQL 错误。
指定 WAITFOR 子句后,该语句将等待指定的超时时间,或等到结果集可用为止。 如果在语句等待时删除队列或队列的状态设置为 OFF,则该语句立即返回一个错误。 如果 RECEIVE 语句指定了会话组或会话句柄,并且用于该会话的服务被删除或移动到另一个队列,则 RECEIVE 语句将报告一个 Transact-SQL 错误。
RECEIVE 在用户定义函数中无效。
下表列出了队列中的列:
列名 | 数据类型 | 说明 |
---|---|---|
status |
tinyint |
消息的状态。 对于由 RECEIVE 命令返回的消息,状态总为 0。 队列中的消息可能包含下列值之一: 0=就绪1=已收到的消息2=尚未完成3=发送后予以保留的消息 |
priority |
tinyint |
0. 标识只是为了提供一些信息。不提供支持。不保证以后的兼容性。. |
queuing_order |
bigint |
消息在该队列中的序号。 |
conversation_group_id |
uniqueidentifier |
此消息所属的会话组的标识符。 |
conversation_handle |
uniqueidentifier |
此消息所属的会话的句柄。 |
message_sequence_number |
bigint |
会话中的消息的序列号。 |
service_name |
nvarchar(512) |
要进行会话的服务的名称。 |
service_id |
int |
要进行会话的服务的 SQL Server 对象标识符。 |
service_contract_name |
nvarchar(256) |
会话遵循的约定的名称。 |
service_contract_id |
int |
会话遵循的约定的 SQL Server 对象标识符。 |
message_type_name |
nvarchar(256) |
说明消息的消息类型的名称。 |
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 = "http://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 = "http://Adventure-Works.com/schemas/expenseReport"
/rpt:ExpenseReport/rpt:ItemDetail')
ELSE NULL
END AS ItemList
FROM ExpenseQueue
), TIMEOUT 60000 ;
请参阅
参考
BEGIN DIALOG CONVERSATION (Transact-SQL)
BEGIN CONVERSATION TIMER (Transact-SQL)
END CONVERSATION (Transact-SQL)
SEND (Transact-SQL)
CREATE QUEUE (Transact-SQL)
ALTER QUEUE (Transact-SQL)
DROP QUEUE (Transact-SQL)
其他资源
Service Broker 教程
Conversation Group Locks
会话体系结构