Compartir vía


RECEIVE (Transact-SQL)

Se aplica a: SQL Server Azure SQL Managed Instance

Recupera uno o más mensajes de una cola. En función del valor de retención de la cola, se quita el mensaje de la cola o se actualiza el estado del mensaje de la cola.

Convenciones de sintaxis de Transact-SQL

Sintaxis

[ 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 }

Argumentos

WAITFOR

Especifica que la instrucción RECEIVE espera a que llegue un mensaje a la cola en caso de no haber ningún mensaje.

TOP( n )

Especifica el número máximo de mensajes que se van a devolver. Si no se especifica esta cláusula, se devuelven todos los mensajes que cumplen los criterios de la instrucción.

column_specifier

*
Especifica que el conjunto de resultados contiene todas las columnas de la cola.

column_name
Nombre de la columna que se va a incluir en el conjunto de resultados.

expression
Nombre de columna, constante, función o combinación de nombres de columnas, constantes y funciones conectados mediante un operador.

column_alias
Nombre alternativo para reemplazar el nombre de la columna en el conjunto de resultados.

FROM

Especifica la cola que contiene los mensajes que se van a recuperar.

database_name
Nombre de la base de datos que contiene la cola desde la que se van a recibir los mensajes. Si no se proporciona database_name, el valor predeterminado es la base de datos actual.

schema_name
Nombre del esquema al que pertenece la cola desde la que se van a recibir los mensajes. Si no se proporciona schema_name, se usa el esquema predeterminado del usuario actual.

queue_name
Nombre de la cola desde la que se reciben los mensajes.

INTO table_variable

Especifica la variable de tabla en la que RECEIVE coloca los mensajes. La variable de tabla debe tener el mismo número de columnas que los mensajes. El tipo de datos de cada columna en la variable de tabla debe ser implícitamente convertible al tipo de datos de la columna correspondiente en los mensajes. Si no se especifica INTO, los mensajes se devuelven como un conjunto de resultados.

WHERE

Especifica la conversación o grupo de conversación para los mensajes recibidos. Si se omite, se devuelven los mensajes del siguiente grupo de conversación disponible.

conversation_handle = conversation_handle
Especifica la conversación para los mensajes recibidos. El identificador de conversación proporcionado debe ser un uniqueidentifier o un tipo que se pueda convertir en uniqueidentifier.

conversation_group_id = conversation_group_id
Especifica el grupo de conversación para los mensajes recibidos. El valor de conversation_group_id proporcionado debe ser un uniqueidentifier o un tipo convertible en uniqueidentifier.

TIMEOUT tiempo_de_espera

Especifica el tiempo, en milisegundos, durante el que la instrucción espera un mensaje. Esta cláusula solo se puede utilizar con la cláusula WAITFOR. Si no se especifica esta cláusula o el tiempo de espera es -1, el tiempo de espera es ilimitado. Si se agota el tiempo de espera, RECEIVE devuelve un conjunto de resultados vacío.

Comentarios

Importante

Si la instrucción RECEIVE no es la primera instrucción de un lote o de un procedimiento almacenado, la instrucción anterior deberá finalizar con un punto y coma (;).

La instrucción RECEIVE lee los mensajes de una cola y devuelve un conjunto de resultados. El conjunto de resultados consta de cero o más filas, cada una de las cuales contiene un mensaje. Si no se usa la cláusula INTO y column_specifier no asigna valores a las variables locales, la instrucción devuelve un conjunto de resultados al programa que realiza la llamada.

Los mensajes devueltos por la instrucción RECEIVE pueden ser de distintos tipos de mensaje. Las aplicaciones pueden usar la columna message_type_name para enrutar cada mensaje al código que administra el tipo de mensaje asociado. Hay dos clases de tipos de mensaje:

  • Tipos de mensaje definidos por la aplicación que se crearon utilizando la instrucción CREATE MESSAGE TYPE. El contrato de Service Broker que se especifica para la conversación define el conjunto de tipos de mensaje definidos por la aplicación que se admiten en una conversación.

  • Mensajes de sistema de Service Broker que devuelven información de estado o error.

La instrucción RECEIVE quita los mensajes recibidos de la cola a menos que la cola especifique la retención de mensajes. Si el valor RETENTION para la cola es ON, la instrucción RECEIVE actualiza la columna status a 0 y deja los mensajes en la cola. Si se revierte una transacción que contiene la instrucción RECEIVE, también se revierten todos los cambios de la cola de la transacción y se devuelven los mensajes a la cola.

Todos los mensajes devueltos por una instrucción RECEIVE pertenecen al mismo grupo de conversación. La instrucción RECEIVE bloquea el grupo de conversación para los mensajes devueltos hasta que se termina la transacción que contiene la instrucción. Una instrucción RECEIVE devuelve mensajes que tienen un status de 1. El conjunto de resultados devuelto por la instrucción RECEIVE se ordena de forma implícita:

  • Si los mensajes de varias conversaciones cumplen las condiciones de la cláusula WHERE, la instrucción RECEIVE devuelve todos los mensajes de una conversación antes de devolver los mensajes para otras conversaciones. Las conversaciones se procesan en orden de nivel de prioridad descendente.

  • Para una conversación determinada, una instrucción RECEIVE devuelve los mensajes en orden message_sequence_number ascendente.

La cláusula WHERE de la instrucción RECEIVE solo puede contener una condición de búsqueda que use conversation_handle o conversation_group_id. La condición de búsqueda no puede contener una o más columnas de las demás columnas de la cola. El valor conversation_handle o conversation_group_id no puede ser una expresión. El conjunto de mensajes que se devuelve depende de las condiciones que se especifican en la cláusula WHERE:

  • Si se especifica conversation_handle, RECEIVE devuelve todos los mensajes de la conversación especificada que están disponibles en la cola.

  • Si se especifica conversation_group_id, RECEIVE devuelve todos los mensajes que están disponibles en la cola de cualquier conversación que forme parte del grupo de conversación especificado.

  • Si no hay ninguna cláusula WHERE, RECEIVE determina qué grupo de conversación:

    • Tiene uno o más mensajes en la cola.

    • No ha sido bloqueado por otra instrucción RECEIVE.

    • Tiene el nivel de prioridad más alto de todos los grupos de conversación que cumplen estos criterios.

    A continuación, RECEIVE devuelve todos los mensajes disponibles en la cola de cualquier conversación que forme parte del grupo de conversación seleccionado.

Si el identificador de conversación o el identificador del grupo de conversación especificado en la cláusula WHERE no existe o no está asociado a la cola especificada, la instrucción RECEIVE devuelve un error.

Si la cola especificada en la instrucción RECEIVE tiene el estado de cola establecido en OFF, la instrucción genera un error de Transact-SQL.

Si se especifica la cláusula WAITFOR, la instrucción espera a que se agote el tiempo de espera especificado o hasta que haya un conjunto de resultados disponible. Si se quita la cola o su estado se establece en OFF mientras la instrucción está esperando, dicha instrucción devuelve un error de inmediato. Si la instrucción RECEIVE especifica un grupo de conversación o un identificador de conversación y se quita o se mueve el servicio para dicha conversación a otra cola, la instrucción RECEIVE notifica de un error de Transact-SQL.

RECEIVE no tiene validez en una función definida por el usuario.

La instrucción RECEIVE no tiene ninguna prevención de colapso de la prioridad. Si una instrucción RECEIVE única bloquea un grupo de conversación y recupera muchos mensajes de conversaciones de prioridad baja, no se podrá recibir ningún mensaje de las conversaciones de prioridad alta del grupo. Para evitar esto, cuando recupere mensajes de conversaciones de prioridad baja, utilice la cláusula TOP para limitar el número de mensajes recuperados por cada instrucción RECEIVE.

Poner las columnas en una cola

La siguiente tabla enumera las columnas que contiene una cola:

Nombre de la columna Tipo de datos Descripción
status tinyint Estado del mensaje. Para los mensajes devueltos por el comando RECEIVE, el estado siempre 0es . Los mensajes de la cola pueden contener uno de los valores siguientes:

0=Listo
1=Mensaje recibido
2=Todavía no se ha completado
3=Mensaje enviado retenido
priority tinyint Nivel de prioridad de la conversación que se aplica al mensaje.
queuing_order bigint Número de orden del mensaje en la cola.
conversation_group_id uniqueidentifier Identificador para el grupo de conversación al que pertenece este mensaje.
conversation_handle uniqueidentifier Identificador para la conversación de la que forma parte este mensaje.
message_sequence_number bigint Número de secuencia del mensaje en la conversación.
service_name nvarchar(128) Nombre del servicio al que se destina la conversación.
service_id int Identificador de objeto de SQL Server del servicio al que se destina la conversación.
service_contract_name nvarchar(128) Nombre del contrato por el que se rige la conversación.
service_contract_id int Identificador de objeto de SQL Server del contrato por el que se rige la conversación.
message_type_name nvarchar(128) Nombre del tipo de mensaje que describe el formato del mensaje. Los mensajes pueden ser tipos de mensaje de aplicación o mensajes del sistema del agente.
message_type_id int Identificador de objeto de SQL Server del tipo de mensaje que describe el mensaje.
validation nchar(2) Validación utilizada para el mensaje.

E=Vacío
N=None
X=XML
message_body varbinary(MAX) Contenido del mensaje.

Permisos

Para recibir un mensaje, el usuario actual debe tener el permiso RECEIVE en la cola.

Ejemplos

A Recepción de todas las columnas de todos los mensajes de un grupo de conversación

En el siguiente ejemplo se reciben todos los mensajes disponibles para el próximo grupo de conversación disponible desde la cola ExpenseQueue. La instrucción devuelve los mensajes como un conjunto de resultados.

RECEIVE * FROM ExpenseQueue ;  

B. Recepción de columnas especificadas para todos los mensajes de un grupo de conversación

En el siguiente ejemplo se reciben todos los mensajes disponibles para el próximo grupo de conversación disponible desde la cola ExpenseQueue. La instrucción devuelve los mensajes como un conjunto de resultados que contiene las columnas conversation_handle, message_type_name y message_body.

RECEIVE conversation_handle, message_type_name, message_body  
FROM ExpenseQueue ;  

C. Recepción del primer mensaje disponible en la cola

En el siguiente ejemplo se recibe el primer mensaje disponible en la cola ExpenseQueue como un conjunto de resultados.

RECEIVE TOP (1) * FROM ExpenseQueue ;  

D. Recepción de todos los mensajes de una conversación especificada

En el siguiente ejemplo se reciben todos los mensajes disponibles para la conversación especificada desde la cola ExpenseQueue como un conjunto de resultados.

DECLARE @conversation_handle UNIQUEIDENTIFIER ;  
  
SET @conversation_handle = <retrieve conversation from database> ;  
  
RECEIVE *  
FROM ExpenseQueue  
WHERE conversation_handle = @conversation_handle ;  

E. Recepción de mensajes para un grupo de conversación especificado

En el siguiente ejemplo se reciben todos los mensajes disponibles para el grupo de conversación especificado desde la cola ExpenseQueue como un conjunto de resultados.

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. Recibir en una variable de tabla

En el siguiente ejemplo se reciben todos los mensajes disponibles para el grupo de conversación especificado desde la cola ExpenseQueue en una variable de tabla.

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. Recibir mensajes y esperar indefinidamente

En el siguiente ejemplo se reciben todos los mensajes disponibles para el próximo grupo de conversación disponible en la cola ExpenseQueue. La instrucción espera hasta que se encuentre disponible un mensaje como mínimo y devuelve a continuación un conjunto de resultados que contiene todas las columnas de mensajes.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue) ;  

H. Recibir mensajes y esperar un intervalo especificado

En el siguiente ejemplo se reciben todos los mensajes disponibles para el próximo grupo de conversación disponible en la cola ExpenseQueue. La instrucción espera 60 segundos o hasta que está disponible un mensaje como mínimo (lo que suceda en primer lugar). La instrucción devuelve un conjunto de resultados que contiene todas las columnas de mensajes, si hay como mínimo un mensaje disponible. En caso contrario, la instrucción devuelve un conjunto de resultados vacío.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue ),  
TIMEOUT 60000 ;  

I. Recibir mensajes, modificar el tipo de una columna

En el siguiente ejemplo se reciben todos los mensajes disponibles para el próximo grupo de conversación disponible en la cola ExpenseQueue. Si el tipo de mensaje indica que el mensaje contiene un documento XML, la instrucción convierte el cuerpo del mensaje a 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. Recibir un mensaje, extraer datos del cuerpo del mensaje, recuperar el estado de la conversación

En el siguiente ejemplo se recibe el siguiente mensaje disponible para el próximo grupo de conversación disponible en la cola ExpenseQueue. Si el mensaje es de tipo //Adventure-Works.com/Expenses/SubmitExpense, la instrucción extrae el Id. de empleado y una lista de los elementos del cuerpo del mensaje. La instrucción recupera además el estado de la conversación de la tabla 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 ;