END CONVERSATION (Transact-SQL)

適用対象:SQL ServerAzure SQL Managed Instance

既存のメッセージ交換の一方の側を終了します。

Transact-SQL 構文表記規則

構文

END CONVERSATION conversation_handle  
   [   [ WITH ERROR = failure_code DESCRIPTION = 'failure_text' ]  
     | [ WITH CLEANUP ]  
    ]  
[ ; ]  

Note

SQL Server 2014 (12.x) 以前のバージョンの Transact-SQL 構文を確認するには、以前のバージョンのドキュメントを参照してください。

引数

conversation_handle
終了するメッセージ交換のメッセージ交換ハンドルを指定します。

WITH ERROR =failure_code
エラー コードです。 Failure_code のデータ型は intです。このエラー コードはユーザー定義のコードであり、メッセージ交換の相手側に送信するエラー メッセージの一部となります。 このエラー コードは 0 よりも大きい値にする必要があります。

DESCRIPTION =failure_text
エラー メッセージです。 Failure_text のデータ型は nvarchar (3000)です。 このエラー テキストはユーザー定義のテキストであり、メッセージ交換の相手側に送信するエラー メッセージの一部となります。

WITH CLEANUP
正常に完了できなかったメッセージ交換の一方の側のメッセージとカタログ ビュー エントリをすべて削除します。 メッセージ交換の相手側にはクリーンアップは通知されません。 Microsoft SQL Server では、メッセージ交換エンドポイントが削除され、転送キューにあるメッセージ交換のすべてのメッセージおよびサービス キューにあるメッセージ交換のすべてのメッセージも削除されます。 管理者は、このオプションを使用して、正常に完了できなかったメッセージ交換のメッセージを削除できます。 たとえば、リモート サービスが永久的に削除された場合、管理者は WITH CLEANUP を使ってこのサービスに対するメッセージを削除できます。 WITH CLEANUP は、Service Broker アプリケーションのコードでは使用しないでください。 受信エンドポイントでメッセージの受信を確認する前に END CONVERSATION WITH CLEANUP が実行されると、送信エンドポイントからそのメッセージが再び送信されます。 これにより、ダイアログが再実行される可能性があります。

注釈

メッセージ交換を終了すると、指定した conversation_handle が属するメッセージ交換グループがロックされます。 メッセージ交換の終了時、Service Broker によってこのメッセージ交換のすべてのメッセージがサービス キューから削除されます。

メッセージ交換が終了した後、アプリケーションではそのメッセージ交換のメッセージを送受信できなくなります。 メッセージ交換を完了するには、メッセージ交換の両方の参加者が END CONVERSATION を呼び出す必要があります。 Service Broker が、メッセージ交換の相手側から終了ダイアログ メッセージまたはエラー メッセージを受信しなかった場合は、Service Broker から相手側に、メッセージ交換が終了したことが通知されます。 この場合、このメッセージ交換のメッセージ交換ハンドルが無効になる一方、メッセージ交換のエンドポイントはアクティブなまま残り、この状態はリモート サービスをホストするインスタンスからメッセージの受信確認が返されるまで継続されます。

メッセージ交換の終了ダイアログ メッセージまたはエラー メッセージが Service Broker でまだ処理されていない場合は、Service Broker からメッセージ交換のリモート側に、メッセージ交換が終了したことが通知されます。 Service Broker からリモート サービスに送信されるメッセージは、指定されるオプションによって異なります。

  • メッセージ交換がエラーなく終了し、リモート サービスへのメッセージ交換がアクティブな状態を継続していると、Service Broker からリモート サービスに、https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog のようなメッセージが送信されます。 このメッセージは、Service Broker によってメッセージ交換の順に転送キューに追加されます。 現在転送キューにあるメッセージ交換のすべてのメッセージは、このメッセージが送信されるよりも前に、Service Broker によって送信されます。

  • メッセージ交換がエラーで終了し、リモート サービスへのメッセージ交換がアクティブな状態を継続していると、Service Broker からリモート サービスに、https://schemas.microsoft.com/SQL/ServiceBroker/Error のようなメッセージが送信されます。 現在転送キューに残っているメッセージ交換のメッセージはすべて、Service Broker によって削除されます。

  • データベース管理者は WITH CLEANUP 句を使用して、正常に完了しなかったメッセージ交換を削除できます。 このオプションでは、メッセージ交換のすべてのメッセージとカタログ ビュー エントリが削除されます。 この場合、メッセージ交換のリモート側にはメッセージ交換が終了したことが通知されません。また、アプリケーションでは送信されたが、ネットワーク経由では転送されていなかったメッセージは受信できないことがあります。 メッセージ交換が正常に完了できない場合にのみ、このオプションを使用してください。

メッセージ交換が終了した後、Transact-SQL SEND ステートメントでそのメッセージ交換ハンドルが指定されると、Transact-SQL エラーが発生します。 メッセージ交換の相手側からメッセージを受信した場合、これらのメッセージは Service Broker によって破棄されます。

メッセージ交換が終了し、そのメッセージ交換の未送信のメッセージがリモート サービス側に残っている場合、未送信のメッセージはリモート サービスによって削除されます。 これはエラーとして扱われないため、リモート サービスはメッセージの削除に関する通知を受信しません。

WITH ERROR 句のエラー コードは、正の数値で指定する必要があります。 負の数値は、Service Broker のエラー メッセージ用に予約されています。

END CONVERSATION は、ユーザー定義の関数では無効です。

アクセス許可

アクティブなメッセージ交換を終了するには、そのメッセージ交換の所有者であるか、sysadmin 固定サーバー ロールまたは db_owner 固定データベース ロールのメンバーであることが必要です。

sysadmin 固定サーバー ロールまたは db_owner 固定データベース ロールのメンバーであれば、WITH CLEANUP を使用して、既に完了したメッセージ交換のメタデータを削除できます。

A. メッセージ交換を終了する

次の例では、@dialog_handle で指定したダイアログを終了します。

END CONVERSATION @dialog_handle ;  

B. メッセージ交換を終了し、エラーを返す

次の例では、処理中のステートメントでエラーがレポートされた場合に、@dialog_handle で指定したダイアログを終了し、エラーを返します。 これは簡単なエラー処理であり、アプリケーションによってはこの方法が適切でない場合があります。

DECLARE
    @dialog_handle UNIQUEIDENTIFIER,
    @ErrorSave INT,
    @ErrorDesc NVARCHAR(100);

BEGIN TRANSACTION;

-- Receive and process message

SET @ErrorSave = @@ERROR;

IF (@ErrorSave <> 0)
    BEGIN
        ROLLBACK TRANSACTION;
        SET @ErrorDesc = N'An error has occurred.';
        END CONVERSATION @dialog_handle
            WITH ERROR = @ErrorSave DESCRIPTION = @ErrorDesc;
    END;
ELSE
    COMMIT TRANSACTION;

C. 正常に完了しなかったメッセージ交換をクリーンアップする

次の例では、@dialog_handle で指定したダイアログを終了します。 SQL Server ではサービス キューと転送キューからすべてのメッセージが直ちに削除され、リモート サービスに通知は送信されません。 このようにクリーンアップと共にダイアログを終了すると、リモート サービスに通知が送信されません。この方法は、リモート サービスで EndDialog または Error メッセージを受信できない場合にのみ使用してください。

END CONVERSATION @dialog_handle WITH CLEANUP;  

参照

BEGIN CONVERSATION TIMER (Transact-SQL)
BEGIN DIALOG CONVERSATION (Transact-SQL)
sys.conversation_endpoints (Transact-SQL)