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
Имя очереди, из которой нужно получать сообщения.

В table_variable

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

WHERE

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

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

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

ТАЙМ-аут

Указывает количество времени, в миллисекундах, в течение которого инструкция должна ожидать сообщение. Это предложение может быть использовано только вместе с предложением 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 возвращает сообщения с .status1 Набор результатов, возвращаемый 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=Готов
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=Нет
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 ;  

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

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