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 返回一个空结果集。

备注

ms186963.note(zh-cn,SQL.90).gif重要提示:
如果 RECEIVE 语句不是批处理或存储过程中的第一条语句,则前面的语句必须以 Transact-SQL 语句终止符分号 (;) 终止。

RECEIVE 语句将从队列读取消息并返回结果集。 返回的结果集包含零行或多行,每行包含一个消息。 如果未使用 INTO 子句,并且 column_specifier 没有为局部变量分配值,则该语句将结果集返回到调用程序。

RECEIVE 语句将从队列中删除已收到的消息,但队列指定消息保持时除外。 当队列的 RETENTION 设置为 ON 时,RECEIVE 语句将 status 列更新为 1,并使消息留在队列中。 当包含 RECEIVE 语句的事务回滚时,该事务中队列的所有更改也会随之回滚,并将消息返回到队列。

RECEIVE 语句返回的所有消息都属于同一个会话组。 RECEIVE 语句将锁定返回的消息所属的会话组,直到包含该语句的事务完成为止。 将 RECEIVE 语句返回的结果集进行隐式排序。 对于给定的会话,RECEIVE 语句将返回 status1 的消息,并将消息按 message_sequence_number 的升序排列。

RECEIVE 语句的 WHERE 子句可能只包含使用 conversation_handleconversation_group_id 的搜索条件。 搜索条件不能包含队列中的任何其他列。 conversation_handleconversation_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_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 队列中下一个可用会话组的所有可用消息: 该语句将等到至少一个消息变为可用为止,然后返回一个包含所有消息列的结果集。

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
会话体系结构

帮助和信息

获取 SQL Server 2005 帮助