RECEIVE (Transact-SQL)
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 ]
| column_alias = expression
} [ ,...n ]
<queue> ::=
{
[ database_name . [ schema_name ] . | schema_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.*
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. Wird database name nicht angegeben, wird standardmäßig die aktuelle Datenbank verwendet.schema_name
Der Name des Schemas, das Besitzer der Warteschlange ist, von der Nachrichten empfangen werden. Wird schema name nicht angegeben, 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. Der bereitgestellte conversation handle muss vom Typ uniqueidentifier oder von einem Typ sein, der in uniqueidentifier konvertiert werden kann.conversation_group_id = conversation_group_id
Gibt die Konversationsgruppe für die empfangenen Nachrichten an. Bei dem für conversation group ID that is angegebenen Wert muss es sich um den Datentyp uniqueidentifier handeln oder um einen Typ, der in uniqueidentifier konvertiert werden kann.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 die Klausel nicht angegeben wird oder das Timeout den Wert -1 hat, dann 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 haben. 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. Ein Ausdruck kann nicht conversation_handle oder conversation_group_id enthalten. 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, schlägt die Anweisung mit einem Transact-SQL-Fehler fehl.
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 RECEIVE-Befehl zurückgegeben werden, ist der Status immer 0. Nachrichten in der Warteschlange können einen der folgenden Werte enthalten: 0=Bereit1=Nachricht empfangen2=Noch nicht abgeschlossen3=Gesendete Nachricht wurde 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(512) |
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(256) |
Name des Vertrags, dem die Konversation entspricht. |
service_contract_id |
int |
SQL Server-Objektbezeichner des Vertrags, dem die Konversation entspricht. |
message_type_name |
nvarchar(256) |
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=LeerN=KeineX=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 sämtlicher Spalten für alle Nachrichten in einer Konversationsgruppe
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 angegebener Spalten für alle Nachrichten in einer Konversationsgruppe
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 angegebene Konversation
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 Konversationsgruppe
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 einer Tabellenvariablen
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 ohne Begrenzung der Wartezeit
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 für 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 und Ä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 und Abrufen des Konversationsstatus
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 = "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 ;
Siehe auch
Verweis
BEGIN DIALOG CONVERSATION (Transact-SQL)
BEGIN CONVERSATION TIMER (Transact-SQL)
END CONVERSATION (Transact-SQL)
CREATE CONTRACT (Transact-SQL)