RECEIVE (Transact-SQL)

Область применения: SQL Server Управляемый экземпляр SQL Azure

Извлекает из очереди одно или несколько сообщений. В зависимости от настройки хранения для очереди удаляет сообщение из очереди или обновляет состояние сообщения в очереди.

Соглашения о синтаксисе 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 ]  
}     [ ,...n ]   
  
<queue> ::=  
{ database_name.schema_name.queue_name | schema_name.queue_name | queue_name }

Аргументы

WAITFOR

Указывает, что инструкция RECEIVE ожидает прибытия сообщения в очередь, если в данный момент сообщений нет.

TOP( n )

Указывает максимальное количество сообщений, которые должны быть возвращены. Если это предложение не указано, возвращаются все сообщения, удовлетворяющие критерию инструкции.

column_specifier

*
Указывает, что результирующий набор содержит все столбцы в очереди.

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

выражение
Имя столбца, константа, функция или любое сочетание имен столбцов, констант и функций, соединенных оператором.

column_alias
Альтернативное имя, заменяющее имя столбца в результирующем наборе.

FROM

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

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

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

queue_name
Имя очереди, из которой нужно получать сообщения.

INTO table_variable

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

WHERE

Указывает диалог или группу сообщений для приема сообщений. Если этот аргумент опущен, возвращаются сообщения из следующей доступной группы сообщений.

conversation_handle = conversation_handle
Указывает диалог для принятых сообщений. Предоставленный дескриптор беседы должен быть уникальным идентификатором или типом, который преобразуется в uniqueidentifier.

conversation_group_id = conversation_group_id
Указывает группу сообщений для принятых сообщений. Указанный идентификатор группы диалога должен иметь тип uniqueidentifier либо тип, который можно преобразовать в uniqueidentifier.

TIMEOUT timeout

Указывает количество времени, в миллисекундах, в течение которого инструкция должна ожидать сообщение. Это предложение может быть использовано только вместе с предложением WAITFOR. Если это предложение не указано или время ожидания -1не указано, время ожидания не ограничено. По истечении времени ожидания инструкция RECEIVE возвращает пустой результирующий набор.

Замечания

Внимание

Если инструкция RECEIVE не является первой в пакете или хранимой процедуре, то предшествующая инструкция должна заканчиваться точкой с запятой (;).

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

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

  • Типы сообщений, определяемые приложениями, которые создаются с помощью инструкции CREATE MESSAGE TYPE. Набор определяемых приложениями типов сообщений, разрешенных в диалоге, определен контрактом Service Broker, настроенным для диалога.

  • Системные сообщения Service Broker, возвращающие состояние или сведения об ошибке.

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

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

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

  • Для данной беседы инструкция RECEIVE возвращает сообщения в порядке возрастания message_sequence_number .

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

Столбцы очереди

В следующей таблице указаны столбцы в очереди.

Имя столбца Тип данных Description
status tinyint Состояние сообщения. Для сообщений, возвращаемых командой RECEIVE, всегда отображается 0состояние. Сообщения в очереди могут иметь одно из следующих состояний:

0=Ready
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) Имя типа сообщения, который описывает формат сообщения. Сообщения могут иметь тип, определенный приложением, или быть системными сообщениями компонента Service Broker.
message_type_id int Идентификатор объекта SQL Server типа сообщения, описывающего сообщение.
validation nchar(2) Проверка, используемая для сообщения:

E=Пустая
N=None
X=XML
message_body varbinary(MAX) Содержимое сообщения.

Разрешения

Для получения сообщения пользователь должен иметь разрешение RECEIVE на очередь.

Примеры

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

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

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

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