RECEIVE (Transact-SQL)

Gilt für: SQL Server Azure SQL Managed Instance

Ruft eine oder mehrere Nachrichten aus einer Warteschlange ab. Je nach den Einstellungen für die Warteschlange wird entweder die Nachricht aus der Warteschlange entfernt oder der Status der Nachricht in der Warteschlange aktualisiert.

Transact-SQL-Syntaxkonventionen

Syntax

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

Argumente

WAITFOR

Gibt an, dass die RECEIVE-Anweisung darauf wartet, dass eine Nachricht für die Warteschlange eintrifft, wenn derzeit keine Nachrichten vorhanden sind.

TOP( n )

Gibt die maximale Anzahl von Nachrichten an, die zurückgegeben werden. Wird diese Klausel nicht angegeben, werden alle Nachrichten zurückgegeben, die die Kriterien der Anweisung erfüllen.

column_specifier

*
Gibt an, dass das Resultset alle Spalten in der Warteschlange umfasst.

column_name
Der Name einer Spalte, die in das Resultset aufgenommen werden soll.

expression
Ein Spaltenname, eine Konstante, eine Funktion oder eine beliebige, durch Operatoren verknüpfte Kombination von Spaltennamen, Konstanten und Funktionen.

column_alias
Ein alternativer Name, der den Spaltennamen im Resultset ersetzt.

FROM

Gibt die Warteschlange an, die die Nachrichten enthält, die abgerufen werden sollen.

database_name
Der Name der Datenbank, die die Warteschlange enthält, von der Nachrichten empfangen werden. Wenn database_name nicht bereitgestellt wird, wird standardmäßig die aktuelle Datenbank verwendet.

schema_name
Der Name des Schemas, das Besitzer der Warteschlange ist, von der Nachrichten empfangen werden. Wenn schema_name nicht angegeben wird, wird standardmäßig das Standardschema für den aktuellen Benutzer verwendet.

queue_name
Der Name der Warteschlange, von der Nachrichten empfangen werden.

INTO table_variable

Gibt die Tabellenvariable an, in der RECEIVE die Nachrichten platziert. Die Tabellenvariable muss die gleiche Anzahl von Spalten wie die Nachrichten enthalten. Die Datentypen der einzelnen Spalten in der Tabellenvariablen müssen implizit in den Datentyp der entsprechenden Spalte in den Nachrichten konvertiert werden können. Wenn INTO nicht angegeben wird, werden die Nachrichten als Resultset zurückgegeben.

WHERE

Gibt die Konversation oder Konversationsgruppe für die empfangenen Nachrichten an. Wird kein Wert angegeben, werden Nachrichten aus der nächsten verfügbaren Konversationsgruppe zurückgegeben.

conversation_handle = conversation_handle
Gibt die Konversation für die empfangenen Nachrichten an. Das bereitgestellte Unterhaltungshandle muss ein eindeutiger Bezeichner oder ein Typ sein, der in einen eindeutigen Eindeutiger wandelbar ist.

conversation_group_id = conversation_group_id
Gibt die Konversationsgruppe für die empfangenen Nachrichten an. Der bereitgestellte Konversationsgruppen-ID muss dem Typ uniqueidentifer oder einem Typ entsprechen, der in uniqueidentifer konvertierbar ist.

TIMEOUT timeout

Gibt in Millisekunden an, wie lange die Anweisung auf eine Nachricht warten soll. Diese Klausel kann nur zusammen mit der WAITFOR-Klausel verwendet werden. Wenn diese Klausel nicht angegeben ist oder das Timeout erfolgt -1, ist die Wartezeit unbegrenzt. Läuft das Timeout ab, gibt RECEIVE ein leeres Resultset zurück.

Hinweise

Wichtig

Wenn es sich bei der RECEIVE-Anweisung nicht um die erste Anweisung in einem Batch oder in einer gespeicherten Prozedur handelt, muss die vorhergehende Anweisung mit einem Semikolon (;) abgeschlossen werden.

Die RECEIVE-Anweisung liest Nachrichten aus einer Warteschlange und gibt ein Resultset zurück. Das zurückgegebene Resultset besteht aus null oder mehr Zeilen, wobei jede Zeile eine Nachricht umfasst. Wenn die INTO-Klausel nicht verwendet wird und column_specifier die Werte nicht lokalen Variablen zuordnet, dann gibt die Anweisung ein Resultset an das aufrufende Programm zurück.

Die Nachrichten, die von der RECEIVE-Anweisung zurückgegeben werden, können von anderen Nachrichtentypen sein. In Anwendungen kann die Spalte message_type_name verwendet werden, um jede Nachricht an Code weiterzuleiten, der den zugehörigen Nachrichtentyp behandelt. Die folgenden zwei Klassen von Nachrichtentypen stehen zur Verfügung:

  • Anwendungsdefinierte Nachrichtentypen, die mit der CREATE MESSAGE TYPE-Anweisung erstellt wurden. Der in einer Konversation zulässige Satz von anwendungsdefinierten Nachrichtentypen wird durch den für die Konversation angegebenen Service Broker-Vertrag definiert.

  • Service Broker-Systemmeldungen, die Status- oder Fehlerinformationen zurückgeben.

Mit der RECEIVE-Anweisung werden erhaltene Nachrichten aus der Warteschlange entfernt, es sei denn, für die Warteschlange ist die Aufbewahrung von Nachrichten festgelegt. Ist als Einstellung für RETENTION für die Warteschlange der Wert ON festgelegt, dann aktualisiert die RECEIVE-Anweisung den Wert in der Spalte status auf 0 und belässt die Nachricht in der Warteschlange. Wenn ein Rollback für eine Transaktion erfolgt, die eine RECEIVE-Anweisung enthält, erfolgt auch ein Rollback für alle Änderungen in der Warteschlange innerhalb der Transaktion, und die Nachrichten werden in die Warteschlange zurückgegeben.

Alle Nachrichten, die von einer RECEIVE-Anweisung zurückgegeben werden, gehören derselben Konversationsgruppe an. Die RECEIVE-Anweisung sperrt die Konversationsgruppe für die zurückgegebenen Nachrichten so lange, bis die Transaktion, die die Anweisung enthält, abgeschlossen ist. Eine RECEIVE-Anweisung gibt Nachrichten zurück, die einen status von 1 aufweisen. Das Resultset, das von einer RECEIVE-Anweisung zurückgegeben wird, ist implizit geordnet.

  • Wenn Nachrichten aus mehreren Konversationen den Bedingungen der WHERE-Klausel entsprechen, gibt die RECEIVE-Anweisung alle Nachrichten aus einer Konversation zurück, bevor Nachrichten für eine andere Konversation zurückgegeben werden. Die Konversationen werden in der Reihenfolge absteigender Priorität verarbeitet.

  • Für eine gegebene Konversation gibt eine RECEIVE-Anweisung Nachrichten in aufsteigender message_sequence_number-Reihenfolge zurück.

Die WHERE-Klausel der RECEIVE-Anweisung kann nur eine Suchbedingung enthalten, in der entweder conversation_handle oder conversation_group_id verwendet wird. Die Suchbedingung kann keine der anderen Spalten in der Warteschlange umfassen. conversation_handle oder conversation_group_id darf kein Ausdruck sein. Welcher Satz an Nachrichten zurückgegeben wird, hängt von den Bedingungen ab, die in der WHERE-Klausel angegeben sind:

  • Wenn conversation_handle angegeben wird, dann gibt RECEIVE alle Nachrichten aus der angegebenen Konversation zurück, die in der Warteschlange verfügbar sind.

  • Wenn conversation_group_id angegeben wird, dann gibt RECEIVE alle Nachrichten zurück, die in der Warteschlange aus Konversationen verfügbar sind, die der angegebenen Konversationsgruppe angehören.

  • Wenn keine WHERE-Klausel angegeben wurde, bestimmt RECEIVE die Konversationsgruppe:

    • Es sind eine oder mehrere Nachrichten in der Warteschlange verfügbar.

    • Wurde nicht von einer anderen RECEIVE-Anweisung gesperrt.

    • Weist von allen Konversationsgruppen, die diese Kriterien erfüllen, die höchste Prioritätsebene auf.

    RECEIVE gibt dann alle Nachrichten zurück, die in der Warteschlange aus Konversationen verfügbar sind, die der ausgewählten Konversationsgruppe angehören.

Ist das in der WHERE-Klausel angegebene Konversationshandle oder der für die Konversationsgruppe angegebene Bezeichner nicht vorhanden oder nicht mit der angegebenen Warteschlange verknüpft, dann gibt die RECEIVE-Anweisung einen Fehler zurück.

Ist als Status für die in der RECEIVE-Anweisung angegebene Warteschlange der Wert OFF festgelegt, tritt bei der Anweisung ein Transact-SQL-Fehler auf.

Wird die WAITFOR-Klausel angegeben, wird mit der Ausführung der Anweisung bis zum Ablauf des angegebenen Timeouts oder so lange gewartet, bis ein Resultset verfügbar ist. Wird die Warteschlange gelöscht, oder wird als Status für die Warteschlange OFF angegeben, während eine Anweisung wartet, gibt die Anweisung sofort einen Fehler zurück. Wenn die RECEIVE-Anweisung eine Konversationsgruppe oder ein Konversationshandle angibt, und wenn der Dienst für diese Konversation gelöscht oder zu einer anderen Warteschlange verschoben wird, dann gibt die RECEIVE-Anweisung einen Transact-SQL-Fehler zurück.

RECEIVE ist in einer benutzerdefinierten Funktion nicht gültig.

Die RECEIVE-Anweisung verfügt über keinen prioritätsbezogenen Ausschlussverhinderungsmechanismus. Wenn eine einzelne RECEIVE-Anweisung eine Konversationsgruppe sperrt und viele Nachrichten aus Konversationen mit niedrigerer Priorität abruft, können keine Nachrichten aus Konversationen mit hoher Priorität in der Gruppe empfangen werden. Um dies beim Abruf von Nachrichten aus Konversationen mit niedriger Priorität zu verhindern, verwenden Sie die TOP-Klausel, um die Anzahl von Nachrichten zu beschränken, die von jeder einzelnen RECEIVE-Anweisung empfangen werden.

Spalten in der Warteschlange

In der folgenden Tabelle werden die Spalten einer Warteschlange aufgelistet.

Spaltenname Datentyp Beschreibung
status tinyint Status der Nachricht. Für Nachrichten, die vom BEFEHL EMPFANGEN zurückgegeben werden, ist der Status immer 0. Nachrichten in der Warteschlange können einen der folgenden Werte enthalten:

0=Bereit
1=Empfangene Nachricht
2=Noch nicht abgeschlossen
3=Gesendete Nachricht beibehalten
priority tinyint Die Prioritätsebene der Konversation, die auf die Nachricht angewendet wird.
queuing_order bigint Fortlaufende Nummer der Nachricht in der Warteschlange.
conversation_group_id uniqueidentifier Bezeichner für die Konversationsgruppe, zu der diese Nachricht gehört.
conversation_handle uniqueidentifier Handle der Konversation, von der diese Nachricht ein Teil ist.
message_sequence_number bigint Sequenznummer der Nachricht in der Konversation.
service_name nvarchar(128) Name des Diensts, an den die Konversation gerichtet ist.
service_id int SQL Server-Objektbezeichner des Diensts, an den die Konversation gerichtet ist.
service_contract_name nvarchar(128) Name des Vertrags, dem die Konversation entspricht.
service_contract_id int SQL Server-Objektbezeichner des Vertrags, dem die Konversation entspricht.
message_type_name nvarchar(128) Name des Nachrichtentyps, der das Format der Nachricht beschreibt. Nachrichten können entweder vom Typ Anwendungsnachricht oder Brokersystemmeldungen sein.
message_type_id int SQL Server-Objektbezeichner des Nachrichtentyps, der die Nachricht beschreibt.
validation nchar(2) Für die Nachricht verwendete Überprüfung.

E=Leer
N=Keine
X=XML
message_body varbinary(MAX) Inhalt der Nachricht.

Berechtigungen

Um eine Nachricht erhalten zu können, muss der aktuelle Benutzer über eine RECEIVE-Berechtigung für die Warteschlange verfügen.

Beispiele

A. Empfangen aller Spalten für alle Nachrichten in einer Unterhaltungsgruppe

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die nächste verfügbare Konversationsgruppe aus der ExpenseQueue-Warteschlange empfangen. Die Anweisung gibt die Nachrichten als Resultset zurück.

RECEIVE * FROM ExpenseQueue ;  

B. Empfangen von angegebenen Spalten für alle Nachrichten in einer Unterhaltungsgruppe

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die nächste verfügbare Konversationsgruppe aus der ExpenseQueue-Warteschlange empfangen. Die Anweisung gibt die Nachrichten als Resultset zurück, das die Spalten conversation_handle, message_type_name und message_body umfasst.

RECEIVE conversation_handle, message_type_name, message_body  
FROM ExpenseQueue ;  

C. Empfangen der ersten verfügbaren Nachricht in der Warteschlange

Im folgenden Beispiel wird die erste verfügbare Nachricht aus der ExpenseQueue-Warteschlange als Resultset empfangen.

RECEIVE TOP (1) * FROM ExpenseQueue ;  

D: Empfangen aller Nachrichten für eine bestimmte Unterhaltung

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die angegebene Konversation aus der ExpenseQueue-Warteschlange als Resultset empfangen.

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

E. Empfangen von Nachrichten für eine angegebene Unterhaltungsgruppe

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die angegebene Konversationsgruppe aus der ExpenseQueue-Warteschlange als Resultset empfangen.

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. Empfangen in eine Tabellenvariable

Im folgenden Beispiel werden alle verfügbaren Nachrichten für eine angegebene Konversationsgruppe aus der ExpenseQueue-Warteschlange in einer Tabellenvariablen empfangen.

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. Empfangen von Nachrichten und Warten auf unbestimmte Zeit

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die nächste verfügbare Konversationsgruppe in der ExpenseQueue-Warteschlange empfangen. Die Anweisung wartet, bis mindestens eine Nachricht verfügbar ist. Sie gibt dann ein Resultset zurück, das alle Nachrichtenspalten enthält.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue) ;  

H. Empfangen von Nachrichten und Warten auf ein angegebenes Intervall

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die nächste verfügbare Konversationsgruppe in der ExpenseQueue-Warteschlange empfangen. Die Anweisung wartet 60 Sekunden oder so lange, bis mindestens eine Nachricht verfügbar ist, je nachdem, welches Ereignis zuerst eintritt. Die Anweisung gibt ein Resultset zurück, das alle Nachrichtenspalten enthält, wenn mindestens eine Nachricht verfügbar ist. Andernfalls gibt die Anweisung ein leeres Resultset zurück.

WAITFOR (  
    RECEIVE *  
    FROM ExpenseQueue ),  
TIMEOUT 60000 ;  

I. Empfangen von Nachrichten, Ändern des Typs einer Spalte

Im folgenden Beispiel werden alle verfügbaren Nachrichten für die nächste verfügbare Konversationsgruppe in der ExpenseQueue-Warteschlange empfangen. Wenn über den Nachrichtentyp angegeben wird, dass die Nachricht ein XML-Dokument enthält, dann konvertiert die Anweisung den Nachrichtentext 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. Empfangen einer Nachricht, Extrahieren von Daten aus dem Nachrichtentext, Abrufen des Unterhaltungszustands

Im folgenden Beispiel wird die nächste verfügbare Nachricht für die nächste verfügbare Konversationsgruppe in der ExpenseQueue-Warteschlange empfangen. Im Falle des Nachrichtentyps //Adventure-Works.com/Expenses/SubmitExpense extrahiert die Anweisung die Employee ID und eine Liste von Elementen aus dem Nachrichtentext. Die Anweisung ruft auch den Status der Konversation aus der ConversationState-Tabelle ab.

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 ;