RECEIVE (Transact-SQL)

Si applica a:SQL ServerIstanza gestita di SQL di Azure

Recupera uno o più messaggi da una coda. A seconda del periodo di memorizzazione impostato per la coda, questa istruzione rimuove il messaggio dalla coda o aggiorna lo stato del messaggio nella coda.

Convenzioni relative alla sintassi Transact-SQL

Sintassi

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

Argomenti

WAITFOR

Specifica che la RECEIVE sentenza attenda che un messaggio arrivi in coda, se attualmente non sono presenti messaggi.

TOP( n )

Specifica il numero massimo di messaggi da restituire. Se questa clausola viene omessa, vengono restituiti tutti i messaggi corrispondenti ai criteri dell'istruzione.

column_specifier

*
Specifica che il set di risultati contiene tutte le colonne nella coda.

column_name
Nome di una colonna da includere nel set di risultati.

expression
Nome di colonna, costante, funzione o qualsiasi combinazione di nomi di colonna, costanti e funzioni concatenati da un operatore.

column_alias
Nome alternativo con cui sostituire il nome di colonna nel set di risultati.

FROM

Specifica la coda contenente i messaggi da recuperare.

database_name
Nome del database contenente la coda da cui ricevere i messaggi. Se non si specifica database_name, per impostazione predefinita viene usato il database corrente.

schema_name
Nome dello schema proprietario della coda da cui ricevere i messaggi. Se non si specifica schema_name, per impostazione predefinita viene usato lo schema predefinito dell'utente corrente.

queue_name
Nome della coda da cui ricevere i messaggi.

VERSO table_variable

Specifica la variabile della tabella in cui RECEIVE si inseriscono i messaggi. La variabile di tabella deve includere un numero di colonne uguale a quello presente nei messaggi. Il tipo di dati di ogni colonna nella variabile di tabella deve supportare la conversione implicita nel tipo di dati della colonna corrispondente nei messaggi. Se non si specifica INTO, i messaggi vengono restituiti come set di risultati.

WHERE

Specifica la conversazione o il gruppo di conversazioni per i messaggi ricevuti. Se la clausola viene omessa, vengono restituiti i messaggi dal successivo gruppo di conversazioni disponibile.

conversation_handle = conversation_handle
Specifica la conversazione per i messaggi ricevuti. L'handledi conversazione fornito deve essere un uniqueidentifier o un tipo convertibile in uniqueidentifier.

conversation_group_id = conversation_group_id
Specifica il gruppo di conversazioni per i messaggi ricevuti. L'ID gruppo di conversazioni specificato deve essere un tipo uniqueidentifier o un tipo convertibile in uniqueidentifier.

TIMEOUT TIMEOUT

Specifica l'intervallo di tempo, in millisecondi, per cui l'istruzione deve rimanere in attesa di un messaggio. È possibile utilizzare questa clausola solo insieme alla clausola WAITFOR. Se questa clausola non è specificata o il timeout è -1, il tempo di attesa è illimitato. Se il time-out scade, RECEIVE restituisce un set di risultati vuoto.

Osservazioni:

Importante

Se l'istruzione RECEIVE non è la prima di una procedura batch o memorizzata, la precedente deve terminare con un punto e virgola (;).

L'istruzione RECEIVE legge i messaggi da una coda e restituisce un insieme di risultati. Il set di risultati è composto da zero o più righe, ognuna contenente un singolo messaggio. Se non si usa la clausola INTO e il parametro column_specifier non assegna valori a variabili locali, l'istruzione restituisce un set di risultati al programma chiamante.

I messaggi restituiti dall'istruzione RECEIVE possono essere di diversi tipi di messaggio. Le applicazioni possono usare la message_type_name colonna per instradare ogni messaggio al codice che gestisce il tipo di messaggio associato. Esistono due classi di tipi di messaggi:

  • Tipi di messaggi definiti dall'applicazione creati utilizzando l'istruzione CREATE MESSAGE TYPE . Il set di tipi di messaggi definiti dall'applicazione consentiti in una conversazione è definito dal contratto di Service Broker specificato per la conversazione.

  • Messaggi del sistema di Service Broker che restituiscono informazioni sullo stato o sull'errore.

L'istruzione RECEIVE rimuove i messaggi ricevuti dalla coda a meno che la coda non specifichi la conservazione dei messaggi. Quando l'impostazione RETENTION per la coda è attiva, l'istruzione RECEIVE aggiorna la status colonna e 0 lascia i messaggi nella coda. Quando una transazione che contiene un'istruzione RECEIVE viene annullata, tutte le modifiche alla coda nella transazione vengono anch'esse annullate, restituendo i messaggi alla coda.

Tutti i messaggi restituiti da un'istruzione RECEIVE appartengono allo stesso gruppo di conversazione. L'istruzione RECEIVE blocca il gruppo di conversazione per i messaggi restituiti fino al termine della transazione che contiene l'istruzione. Un'istruzione restituisce RECEIVE messaggi che hanno un status .1 L'insieme dei risultati restituito da un'affermazione RECEIVE è implicitamente ordinato:

  • Se i messaggi provenienti da più conversazioni soddisfano le condizioni della clausola WHERE, l'istruzione RECEIVE restituisce tutti i messaggi di una conversazione prima di restituire quelli di un'altra. Le conversazioni vengono elaborate in ordine di livello di priorità decrescente.

  • Per una data conversazione, una RECEIVE dichiarazione restituisce i messaggi in ordine crescente message_sequence_number .

La clausola WHERE dell'enunciato RECEIVE può contenere solo una condizione di ricerca che utilizza o conversation_handle o conversation_group_id. La condizione di ricerca non può contenere una o più altre colonne nella coda. conversation_handle o conversation_group_id non può essere un'espressione. Il set di messaggi restituito dipende dalle condizioni specificate nella clausola WHERE:

  • Se conversation_handle è specificato, RECEIVE restituisce tutti i messaggi della conversazione specificata che sono disponibili nella coda.

  • Se conversation_group_id è specificato, RECEIVE restituisce tutti i messaggi disponibili nella coda da qualsiasi conversazione che sia membro del gruppo di conversazione specificato.

  • Se non esiste una clausola WHERE, RECEIVE determina quale gruppo di conversazione:

    • Dispone di uno o più messaggi nella coda.

    • Non è stato bloccato da un'altra RECEIVE dichiarazione.

    • Ha il livello di priorità più elevato di tutti i gruppi di conversazioni che soddisfano questi criteri.

    RECEIVE poi restituisce tutti i messaggi disponibili in coda provenienti da qualsiasi conversazione appartenente al gruppo di conversazione selezionato.

Se il handle della conversazione o l'identificatore del gruppo di conversazione specificato nella clausola WHERE non esiste, o non è associato alla coda specificata, l'istruzione RECEIVE restituisce un errore.

Se la coda specificata nell'istruzione RECEIVE ha lo stato della coda impostato su OFF, l'istruzione fallisce con un errore Transact-SQL.

Se si specifica la clausola WAITFOR, l'istruzione rimane in attesa per il periodo di timeout specificato oppure fino a quando non è disponibile un set di risultati. Se la coda viene eliminata o lo stato della coda viene impostato su OFF mentre l'istruzione è in attesa, l'istruzione restituisce immediatamente un errore. Se l'istruzione RECEIVE specifica un gruppo di conversazione o un handle di conversazione e il servizio per quella conversazione viene abbandonato o spostato in un'altra coda, l'istruzione RECEIVE segnala un errore di Transact-SQL.

RECEIVE non è valido in una funzione definita dall'utente.

La RECEIVE dichiarazione non prevede priorità nella prevenzione della fame. Se una singola RECEIVE istruzione blocca un gruppo di conversazione e recupera molti messaggi da conversazioni a bassa priorità, nessun messaggio può essere ricevuto da conversazioni ad alta priorità nel gruppo. Per evitare ciò, quando recuperi messaggi da conversazioni a bassa priorità, usa la clausola TOP per limitare il numero di messaggi recuperati da ogni RECEIVE istruzione.

Colonne della coda

Nella tabella seguente vengono elencate le colonne di una coda:

Nome colonna Tipo di dati Descrizione
status tinyint Stato del messaggio. Per i messaggi restituiti dal RECEIVE comando, lo stato è sempre 0. I messaggi nella coda possono contenere uno dei valori seguenti:

0=Pronto
1=Messaggio ricevuto
2=Non ancora completato
3=Messaggio inviato conservato
priority tinyint Livello di priorità della conversazione applicato al messaggio.
queuing_order bigint Numero progressivo del messaggio nella coda.
conversation_group_id uniqueidentifier Identificatore del gruppo di conversazioni a cui appartiene il messaggio.
conversation_handle uniqueidentifier Handle della conversazione di cui fa parte il messaggio.
message_sequence_number bigint Numero di sequenza del messaggio nella conversazione.
service_name nvarchar(128) Nome del servizio a cui è destinata la conversazione.
service_id int Identificatore di oggetto di SQL Server del servizio a cui è destinata la conversazione.
service_contract_name nvarchar(128) Nome del contratto rispettato dalla conversazione.
service_contract_id int Identificatore di oggetto di SQL Server del contratto rispettato dalla conversazione.
message_type_name nvarchar(128) Nome del tipo di messaggio che descrive il formato del messaggio. I messaggi possono essere tipi di messaggi dell'applicazione o messaggi di sistema di Service Broker.
message_type_id int Identificatore di oggetto di SQL Server del tipo di messaggio che descrive il messaggio.
validation nchar(2) Convalida utilizzata per il messaggio.

E=Vuoto
N=Nessuno
X=XML
message_body varbinary(MAX) Contenuto del messaggio.

Autorizzazioni

Per ricevere un messaggio, l'utente attuale deve avere RECEIVE il permesso di accedere alla coda.

Esempi

R. Ricevere tutte le colonne per tutti i messaggi in un gruppo di conversazioni

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. L'istruzione restituisce i messaggi in forma di set di risultati.

RECEIVE * FROM ExpenseQueue ;  

B. Ricevere colonne specificate per tutti i messaggi in un gruppo di conversazioni

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. L'istruzione restituisce i messaggi in forma di set di risultati contenente le colonne conversation_handle, message_type_name e message_body.

RECEIVE conversation_handle, message_type_name, message_body  
FROM ExpenseQueue ;  

C. Ricevere il primo messaggio disponibile nella coda

Nell'esempio seguente, l'istruzione è impostata per la ricezione del primo messaggio disponibile dalla coda ExpenseQueue in forma di set di risultati.

RECEIVE TOP (1) * FROM ExpenseQueue ;  

D. Ricevere tutti i messaggi per una conversazione specificata

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per la conversazione specificata dalla coda ExpenseQueue in forma di set di risultati.

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

E. Ricevere messaggi per un gruppo di conversazioni specificato

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il gruppo di conversazioni specificato dalla coda ExpenseQueue in forma di set di risultati.

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. Ricevere in una variabile di tabella

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il gruppo di conversazioni specificato dalla coda ExpenseQueue in una variabile di tabella.

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. Ricevere messaggi e attendere indefinito

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. L'istruzione attende fino a quando non diventa disponibile almeno un messaggio, quindi restituisce un set di risultati contenente tutte le colonne del messaggio.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue) ;  

H. Ricevere messaggi e attendere un intervallo specificato

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. L'istruzione attende 60 secondi o fino a quando non diventa disponibile almeno un messaggio, a seconda dell'evento che si verifica per primo. L'istruzione restituisce un set di risultati contenente tutte le colonne del messaggio, se è disponibile almeno un messaggio. In caso contrario, l'istruzione restituisce un set di risultati vuoto.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue ),  
TIMEOUT 60000 ;  

I. Ricevere messaggi, modificando il tipo di una colonna

Nell'esempio seguente, l'istruzione è impostata per la ricezione di tutti i messaggi disponibili per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. Se il tipo di messaggio indica che il messaggio contiene un documento XML, l'istruzione converte il corpo del messaggio in 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. Ricevere un messaggio, estrarre dati dal corpo del messaggio, recuperando lo stato della conversazione

Nell'esempio seguente, l'istruzione è impostata per la ricezione del successivo messaggio disponibile per il successivo gruppo di conversazioni disponibile dalla coda ExpenseQueue. Se il messaggio è di tipo //Adventure-Works.com/Expenses/SubmitExpense, l'istruzione estrae l'ID del dipendente e un elenco di elementi dal corpo del messaggio. L'istruzione recupera inoltre lo stato della conversazione dalla tabella 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 ;