クエリ通知の操作
適用対象: SQL Server
Azure SQL Managed Instance
重要
SQL Server Native Client (SNAC) は同梱されていません。
- SQL Server 2022 (16.x) 以降のバージョン
- SQL Server Management Studio 19 以降のバージョン
SQL Server Native Client (SQLNCLI または SQLNCLI11) と従来の Microsoft OLE DB Provider for SQL Server (SQLOLEDB) は、新しいアプリケーション開発には推奨されません。
新しいプロジェクトの場合は、次のいずれかのドライバーを使用します。
SQL Server データベース エンジン (バージョン 2012 から 2019) のコンポーネントとして付属する SQLNCLI については、この「サポート ライフサイクルの例外」を参照してください。
クエリ通知は、SQL Server 2005 (9.x) と SQL Server Native Client で導入されました。 SQL Server 2005 (9.x) で導入された Service Broker インフラストラクチャに基づいて構築されたクエリ通知を使用すると、データが変更されたときにアプリケーションに通知できます。 この機能は、Web アプリケーションなど、データベースから情報のキャッシュを提供し、ソース データが変更された場合に通知を必要とするアプリケーションに特に役立ちます。
クエリ通知を使用すると、クエリの基になるデータが変更された場合に、指定されたタイムアウト期間内に通知を要求することができます。 通知を要求する際は、サービス名、メッセージ テキスト、サーバーのタイムアウト値などの通知オプションを指定します。 通知は Service Broker キューを使用して配信されます。アプリケーションではこのキューにポーリングして、使用可能な通知を確認できます。
クエリ通知オプションの構文を次に示します。
service=<service-name>[;(local database=<database> | broker instance=<broker instance>)]
次に例を示します。
service=mySSBService;local database=mydb
アプリケーションで通知サブスクリプションが作成された直後にそのアプリケーションが終了した場合、通知サブスクリプションを開始するプロセスが終了しても、通知サブスクリプションは有効です。 通知サブスクリプションが有効なままなので、通知サブスクリプションの作成時に指定したタイムアウト期間内にデータが変更されると、通知が行われます。 通知は、実行されるクエリ、通知オプション、およびメッセージ テキストによって識別されます。また、通知のタイムアウト値を 0 に設定して通知をキャンセルできます。
通知は、一度だけ送信されます。 データ変更の通知を連続して行う場合は、各通知が処理された後にクエリを再実行して、新しいサブスクリプションを作成する必要があります。
SQL Server Native Client アプリケーションは、通常、Transact-SQL RECEIVE コマンドを使用して通知を受信し、通知オプションで指定されたサービスに関連付けられているキューから通知を読み取ります。
Note
通知を必要とするクエリ内のテーブル名は、dbo.myTable
のように、修飾された名前にする必要があります。 テーブル名は、2 つの部分を持つ修飾名にする必要があります。 3 つまたは 4 つの部分を持つ名前を使用すると、サブスクリプションが無効になります。
この通知インフラストラクチャは、SQL Server 2005 (9.x) で導入されたキュー処理機能に基づいて構築されています。 一般的に、サーバーで生成された通知は、後で処理するためにキュー経由で送信されます。
クエリ通知を使用するには、クエリとサービスがサーバー上に存在する必要があります。 これらは、次のような Transact-SQL を使用して作成できます。
CREATE QUEUE myQueue
CREATE SERVICE myService ON QUEUE myQueue
([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
Note
上記のように、サービスでは定義済みのコントラクト http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification
を使用する必要があります。
SQL Server Native Client OLE DB プロバイダー
SQL Server Native Client OLE DB プロバイダーは、行セットの変更に関するコンシューマー通知をサポートします。 コンシューマーは、行セットの変更のすべてのフェーズで、任意の変更が試行されたときに通知を受け取ります。
Note
DBPROPSET_SQLSERVERROWSET プロパティ セット
OLE DB を介したクエリ通知をサポートするために、SQL Server Native Client は次の新しいプロパティを DBPROPSET_SQLSERVERROWSET プロパティ セットに追加します。
名前 | 種類 | 説明 |
---|---|---|
SSPROP_QP_NOTIFICATION_TIMEOUT | VT_UI4 | クエリ通知をアクティブのままにしておく秒数。 既定値は 432,000 秒 (5 日) です。 最小値は 1 秒であり、最大値は 2^31-1 秒です。 |
SSPROP_QP_NOTIFICATION_MSGTEXT | VT_BSTR | 通知のメッセージ テキスト。 これはユーザーが定義するため、あらかじめ定義済みの書式はありません。 既定では、文字列は空です。 1 ~ 2,000 文字を使用してメッセージを指定できます。 |
SSPROP_QP_NOTIFICATION_OPTIONS | VT_BSTR | クエリ通知オプション。 これらは name=value 構文を使用した文字列で指定されます。 ユーザーがサービスを作成して、キューから通知を読み取る必要があります。 既定値は空の文字列です。 |
ステートメントがユーザー トランザクションで実行されたか自動コミットで実行されたか、また、ステートメントが実行されたトランザクションがコミットされたかロールバックされたかに関係なく、通知サブスクリプションは必ずコミットされます。 サーバー通知は、次の無効通知条件のいずれかが最初に発生したときに起動します。通知条件は、基になるデータまたはスキーマが変更されるか、タイムアウト期間に到達するかです。 通知登録は、起動直後に削除されます。 したがって、通知を受け取った後も引き続き更新するには、アプリケーションで再度サブスクライブする必要があります。
他の接続またはスレッドは、接続先キューに通知があるかどうかを確認できます。 次に例を示します。
WAITFOR (RECEIVE * FROM MyQueue); // Where MyQueue is the queue name.
SELECT * はキューからエントリを削除しませんが、RECEIVE * FROM は削除されることに注意してください。 このため、キューが空の場合は、サーバー スレッドが保留されます。 呼び出し時にキュー エントリがあれば、それらがすぐに返されます。それ以外の場合、呼び出しは、キュー エントリが作成されるまで待機します。
RECEIVE * FROM MyQueue
キューが空の場合、このステートメントは空の結果セットを直ちに返します。それ以外の場合、すべてのキュー通知を返します。
SSPROP_QP_NOTIFICATION_MSGTEXT と SSPROP_QP_NOTIFICATION_OPTIONS が NULL 以外で、かつ空ではない場合、上記で定義された 3 つのプロパティを含んでいるクエリ通知 TDS ヘッダーが、コマンドが実行されるたびにサーバーに送信されます。 どちらかが NULL (または空) の場合、クエリ通知 TDS ヘッダーは送信されず、DB_E_ERRORSOCCURED (または、プロパティが両方とも省略可能に設定されている場合は DB_S_ERRORSOCCURED) が発生し、状態値が DBPROPSTATUS_BADVALUE に設定されます。 実行または準備の時点で検証が行われます。 同様に、DB_S_ERRORSOCCUREDは、SQL Server 2005 (9.x) より前のバージョンの SQL Server への接続に対してクエリ通知プロパティが設定されている場合に発生します。 この場合の状態値は DBPROPSTATUS_NOTSUPPORTED です。
サブスクリプションが開始されても、後続のメッセージが正常に配信されるかどうかは保証されません。 また、指定されたサーバー名の妥当性に関するチェックは行われません。
Note
ステートメントの準備フェーズではサブスクリプションが開始されることはありません。サブスクリプションは、ステートメントを実行したときにのみ開始されます。また、OLE DB Core Services を使用してもクエリ通知は影響を受けません。
DBPROPSET_SQLSERVERROWSET プロパティ セットの詳細については、「 Rowset のプロパティと動作を参照してください。
SQL Server Native Client ODBC ドライバー
SQL Server Native Client ODBC ドライバーは、 SQLGetStmtAttr および SQLSetStmtAttr 関数に次の 3 つの新しい属性を追加してクエリ通知をサポートします。
SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT
SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS
SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT
SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT と SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS が NULL 以外の場合、上記で定義された 3 つの属性を含むクエリ通知 TDS ヘッダーが、コマンドを実行するたびにサーバーに送信されます。 どちらかが NULL の場合、クエリ通知 TDS ヘッダーは送信されず、SQL_SUCCESS_WITH_INFO が返されます。 検証は、 SQLPrepare 関数、 SqlExecDirect、および SqlExecute で行われ、属性が無効な場合は失敗します。 同様に、SQL Server 2005 (9.x) より前のバージョンの SQL Server に対してこれらのクエリ通知属性が設定されている場合、実行はSQL_SUCCESS_WITH_INFOで失敗します。
Note
ステートメントの準備段階では、サブスクリプションが開始されることはありません。サブスクリプションを開始できるのは、ステートメントを実行したときのみです。
特別なケースおよび制限
通知では、次のデータ型がサポートされていません。
text
ntext
image
これらのいずれかのデータ型を返すクエリに対して通知要求を作成すると、通知サブスクリプションが不可能であるという通知が、すぐに発行されます。
バッチまたはストアド プロシージャに対するサブスクリプション要求を作成すると、そのバッチまたはストアド プロシージャ内で実行される各ステートメントに対して、別個のサブスクリプション要求が作成されます。 EXECUTE ステートメントは通知を登録せず、実行されるコマンドへ通知要求を送信します。 バッチの場合、実行されるステートメントに対してコンテキストが適用され、さらに同様のルールが適用されます。
同じデータベース コンテキストで同じユーザーによって送信され、同じテンプレート、同じパラメーター値、同じ通知 ID、および既存のアクティブなサブスクリプションの同じ配信場所を持つ通知のクエリを送信すると、既存のサブスクリプションが更新され、新しく指定されたタイムアウトがリセットされます。つまり、同じクエリに対して通知が要求された場合、1 つの通知のみが送信されます。 バッチ内で重複するクエリや、ストアド プロシージャ内で複数回呼び出されたクエリにも、これが当てはまります。