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(ru-ru,SQL.90).gifВажно!
Если инструкция RECEIVE не первая в пакете или является хранимой процедурой, то предшествующая инструкция должна заканчиваться точкой с запятой (;), признаком конца инструкции языка Transact-SQL.

Инструкция RECEIVE считывает сообщения из очереди и возвращает результирующий набор. Возвращаемый результирующий набор может быть пустым или содержать несколько строк, каждая из которых содержит одно сообщение. Если предложение INTO не используется, а аргумент column_specifier не присваивает значения локальным переменным, инструкция возвращает результирующий набор вызывающей программе.

Инструкция RECEIVE удаляет полученные сообщения из очереди, если только очередь не указывает сохранение сообщений. Если параметр RETENTION для очереди установлен в ON, инструкция RECEIVE устанавливает столбец status в 1 и оставляет сообщение в очереди. Если транзакция, содержащая инструкцию RECEIVE, выполняет откат, производится также откат всех изменений в очереди в пределах транзакции, сообщения при этом возвращаются в очередь.

Все сообщения, возвращаемые инструкцией RECEIVE, принадлежат к одной и той же группе сообщений. Инструкция RECEIVE блокирует группу сообщений для возвращенных сообщений до тех пор, пока не завершится транзакция, содержащая инструкцию. Результирующий набор, возвращенный инструкцией RECEIVE, неявно упорядочен. Для данного диалога инструкция RECEIVE возвращает сообщения со значением status, равным1 в порядке возрастания столбца message_sequence_number.

Предложение WHERE инструкции RECEIVE может содержать только условия поиска, использующие аргумент 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 на очередь.

Примеры

А. Получение всех столбцов для всех сообщений в группе сообщений

На следующем примере показано, как получаются все доступные сообщения для следующей доступной группы сообщений из очереди ExpenseQueue. Инструкция возвращает сообщения в виде результирующего набора.

RECEIVE * FROM ExpenseQueue ;

Б. Получение указанных столбцов для всех сообщений в группе сообщений

На следующем примере показано, как получаются все доступные сообщения для следующей доступной группы сообщений из очереди ExpenseQueue. Инструкция возвращает сообщения в виде результирующего набора, содержащего столбцы conversation_handle, message_type_name и message_body.

RECEIVE conversation_handle, message_type_name, message_body
FROM ExpenseQueue ;

В. Получение первого доступного сообщения в очереди

На следующем примере показано, как в качестве результирующего набора возвращается первое доступное сообщение из очереди ExpenseQueue.

RECEIVE TOP (1) * FROM ExpenseQueue ;

Г. Получение всех сообщений для указанного диалога

На следующем примере показано, как в качестве результирующего набора возвращаются все доступные сообщения для указанного диалога из очереди ExpenseQueue.

DECLARE @conversation_handle UNIQUEIDENTIFIER ;

SET @conversation_handle = <retrieve conversation from database> ;

RECEIVE *
FROM ExpenseQueue
WHERE conversation_handle = @conversation_handle ;

Д. Получение сообщений для заданной группы сообщений

На следующем примере показано, как в качестве результирующего набора возвращаются все доступные сообщения для указанной группы сообщений из очереди 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 ;

Е. Получение сообщений в переменную-таблицу

На следующем примере показано, как в переменную-таблицу принимаются все доступные сообщения для указанной группы диалога из очереди 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 ;

Ж. Получение сообщений без ограничения времени ожидания

На следующем примере показано, как получаются все доступные сообщения для следующей доступной группы сообщений в очереди ExpenseQueue. Инструкция ожидает до тех пор, пока, по меньшей мере, одно сообщение не станет доступным, после чего возвращает результирующий набор, содержащий все столбцы сообщения.

WAITFOR (
    RECEIVE *
    FROM ExpenseQueue) ;

З. Получение сообщений с ожиданием в течение указанного интервала времени

На следующем примере показано, как получаются все доступные сообщения для следующей доступной группы сообщений в очереди ExpenseQueue. Инструкция ожидает в течение 60 секунд или до тех пор, пока по меньшей мере одно сообщение не станет доступным (в зависимости от того, что произойдет раньше). При условии, что доступно хотя бы одно сообщение, инструкция возвращает результирующий набор, содержащий все столбцы сообщения. В противном случае инструкция возвращает пустой результирующий набор.

WAITFOR (
    RECEIVE *
    FROM ExpenseQueue ),
TIMEOUT 60000 ;

И. Получение сообщений с изменением типа столбца

На следующем примере показано, как получаются все доступные сообщения для следующей доступной группы сообщений в очереди 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 ;

К. Получение сообщений, извлечение данных из тела сообщения, извлечение состояние диалога

На следующем примере показано, как получается следующее доступное сообщение в очереди ExpenseQueue для следующей доступной группы сообщений. Если сообщение имеет тип //Adventure-Works.com/Expenses/SubmitExpense, инструкция извлекает из тела сообщения идентификатор служащего и список элементов. Инструкция извлекает также состояние для диалога из таблицы 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