RECEIVE (Transact-SQL)

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

Применимо для следующих объектов: SQL Server (начиная с SQL Server 2008 до текущей версии).

Значок ссылки на раздел Cинтаксические обозначения в 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
    Указывает табличную переменную, в которую инструкция RECEIVE записывает сообщения. У табличной переменной должно быть столько же столбцов, сколько и в сообщениях. Тип данных каждого столбца в табличной переменной должен поддерживать неявное преобразование к типу данных соответствующего столбца в сообщениях. Если ключевое слово INTO не указано, сообщения возвращаются в виде результирующего набора.

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

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

  • conversation_group_id = conversation_group_id
    Указывает группу сообщений для принятых сообщений. Аргумент conversation group ID that is должен иметь тип данных 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 для очереди установлен в ON, инструкция 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.

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

Следующая таблица содержит столбцы в очереди.

Имя столбца

Тип данных

Описание

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(512)

Имя службы, к которой относится диалог.

service_id

int

Идентификатор объекта службы SQL Server, к которой относится диалог.

service_contract_name

nvarchar(256)

Имя контракта, которому следует диалог.

service_contract_id

int

Идентификатор объекта контракта SQL Server, которому следует диалог.

message_type_name

nvarchar(256)

Имя типа сообщения, который описывает формат сообщения. Сообщения могут иметь тип, определенный приложением, или быть системными сообщениями компонента Service Broker.

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)

Инструкция CREATE CONTRACT (Transact-SQL)

CREATE MESSAGE TYPE (Transact-SQL)

SEND (Transact-SQL)

CREATE QUEUE (Transact-SQL)

ALTER QUEUE (Transact-SQL)

DROP QUEUE (Transact-SQL)