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 陳述式會將狀態資料行更新為 1,並將訊息保留在佇列中。當包含 RECEIVE 陳述式的交易回復時,也會回復交易內的所有佇列變更,且會將訊息傳回給佇列。
RECEIVE 陳述式傳回的所有訊息都屬於相同的交談群組。RECEIVE 陳述式會鎖定傳回訊息的交談群組,直到包含陳述式的交易完成為止。RECEIVE 陳述式傳回的結果集會隱含地排序。對於給定的交談,RECEIVE 陳述式以遞增 message_sequence_number 的順序,傳回狀態為 1 的訊息。
RECEIVE 陳述式的 WHERE 子句只能包含使用 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 權限。
範例
A. 接收交談群組中全部訊息的所有資料行
下列範例接收 ExpenseQueue
佇列中下一個可用交談群組的所有可用訊息。陳述式將訊息當作結果集傳回。
RECEIVE * FROM ExpenseQueue ;
B. 接收交談群組中全部訊息的指定資料行
下列範例接收 ExpenseQueue
佇列中下一個可用交談群組的所有可用訊息。陳述式將訊息當作包含 conversation_handle
、message_type_name
和 message_body
等資料行的結果集傳回。
RECEIVE conversation_handle, message_type_name, message_body
FROM ExpenseQueue ;
C. 接收佇列中第一個可用的訊息
下列範例從 ExpenseQueue
佇列中接收第一個可用的訊息來作為結果集。
RECEIVE TOP (1) * FROM ExpenseQueue ;
D. 接收指定交談的所有訊息
下列範例從 ExpenseQueue
佇列中接收指定交談的所有可用訊息來作為結果集。
DECLARE @conversation_handle UNIQUEIDENTIFIER ;
SET @conversation_handle = <retrieve conversation from database> ;
RECEIVE *
FROM ExpenseQueue
WHERE conversation_handle = @conversation_handle ;
E. 接收指定交談群組的訊息
下列範例從 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 ;
F. 接收並放入資料表變數
下列範例從 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 ;
G. 接收訊息並無限期等候
下列範例接收 ExpenseQueue
佇列中下一個可用交談群組的所有可用訊息。陳述式會等候到至少有一個可用的訊息,再傳回包含所有訊息資料行的結果集。
WAITFOR (
RECEIVE *
FROM ExpenseQueue) ;
H. 接收訊息並等候指定的間隔
下列範例接收 ExpenseQueue
佇列中下一個可用交談群組的所有可用訊息。陳述式會等候 60 秒,或等到至少有一個可用的訊息,兩者中取其先發生者。如果至少有一個可用的訊息,陳述式會傳回包含所有訊息資料行的結果集,否則,就傳回空的結果集。
WAITFOR (
RECEIVE *
FROM ExpenseQueue ),
TIMEOUT 60000 ;
I. 接收訊息,修改資料行的類型
下列範例接收 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 ;
J. 接收訊息、從訊息主體擷取資料、擷取交談狀態
下列範例接收 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
交談架構