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 возвращает пустой результирующий набор.
Замечания
Важно! |
---|
Если инструкция 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
Архитектура диалога