WMI Provider for Server イベントで WQL を使用する

適用対象:SQL Server

管理アプリケーションは、WMI クエリ言語 (WQL) ステートメントを発行して、WMI Provider for Server イベントを使用して SQL Server イベントにアクセスします。 WQL は、WMI 特有の拡張機能を複数持つ、構造化照会言語 (SQL) の単純化されたサブセットです。 WQL を使用する場合、アプリケーションは SQL Server、データベース、またはデータベース オブジェクトの特定のインスタンスに対してイベントの種類を取得します (現在サポートされているオブジェクトはキューのみです)。 WMI Provider for Server Events は、データベース スコープまたはオブジェクト スコープのイベント通知のターゲット データベース、またはサーバー スコープのイベント通知用のデータベースで master 作成されたイベント通知にクエリを変換します。

たとえば、次の WQL クエリを考えてみましょう。

SELECT * FROM DDL_DATABASE_LEVEL_EVENTS WHERE DatabaseName = 'AdventureWorks2022'

このクエリから、WMI プロバイダーは、このイベント通知と同等のものをターゲット サーバー上に生成しようとします。

USE AdventureWorks2022;
GO

CREATE EVENT NOTIFICATION SQLWEP_76CF38C1_18BB_42DD_A7DC_C8820155B0E9
    ON DATABASE
    WITH FAN_IN
    FOR DDL_DATABASE_LEVEL_EVENTS
    TO SERVICE
        'SQL/Notifications/ProcessWMIEventProviderNotification/v1.0',
        'A7E5521A-1CA6-4741-865D-826F804E5135';
GO

WQL クエリ (FROM) の DDL_DATABASE_LEVEL_EVENTS 句の引数には、イベント通知を作成できる有効なイベントを指定することができます。 SELECT 句および WHERE 句の引数は、イベントまたはその親イベントに関連付けられたイベント プロパティを指定することができます。 有効なイベントとイベントのプロパティの一覧については、「イベント通知 (データベース エンジン)」を参照してください

次の WQL 構文は、WMI Provider for Server Events によって明示的にサポートされます。 追加の WQL 構文を指定することもできますが、このプロバイダーに固有ではなく、WMI ホスト サービスによって解析されます。 WMI Query Language の詳細については、Microsoft Developer Network (MSDN) の WQL のドキュメントを参照してください。

構文

SELECT { event_property [ , ...n ] | * }
FROM event_type
WHERE where_condition
[ ; ]

引数

event_property [ , ...n ] |*

イベントのプロパティ。 例には、PostTimeSPID、および LoginName が含まれています。 WMI Provider for Server Events クラスとプロパティ一覧表示されている各イベントを検索して、保持するプロパティを決定します。 たとえば、DDL_DATABASE_LEVEL_EVENTS イベントには、DatabaseName プロパティおよび UserName プロパティがあります。 また、親イベントから SQLInstance プロパティ、LoginName プロパティ、PostTime プロパティ、SPID プロパティ、および ComputerName プロパティを継承しています。

  • ...N

    event_propertyをコンマで区切って複数回照会できることを示します。

  • *

    イベントに関連付けられたすべてのプロパティを照会することを指定します。

event_type

イベント通知を作成できるイベント。 使用可能なイベントの一覧については、「WMI Provider for Server Events のクラスとプロパティ」を参照してくださいイベントの種類の名前は、手動でイベント通知CREATE EVENT NOTIFICATIONを作成するときに指定できるのと同じevent_type | event_groupに対応します。 イベントの種類の例にはCREATE_TABLE、、 DDL_USER_EVENTSLOCK_DEADLOCKTRC_DATABASE

Note

DDL に似た操作を実行する一部のシステム ストアド プロシージャもイベント通知を起動することができます。 イベント通知はテストして、実行されているシステム ストアド プロシージャに応答するかどうか、確認してください。 たとえば、 CREATE TYPE ステートメントと sp_addtype ストアド プロシージャの両方で、イベントに対 CREATE_TYPE して作成されたイベント通知が発生します。 ただし、 sp_rename ストアド プロシージャはイベント通知を発生しません。 詳細については、「DDL イベント」を参照してください

where_condition

WHERE event_property名と論理演算子と比較演算子で構成される句クエリ述語。 where_condition、対応するイベント通知がターゲット データベースに登録されるスコープを決定します。 また、event_typeのクエリの対象となる特定のスキーマまたはオブジェクトを対象とするフィルターとして機能することもできます。詳細については、「解説」セクションを参照してください。

DatabaseNameSchemaName、および ObjectName と共に使用できるのは、= オペランドのみです。 他の式は、これらのイベント プロパティでは使用できません。

解説

WMI Provider for Server Events 構文のwhere_conditionによって、次の内容が決まります。

  • プロバイダーが指定した event_type (サーバー レベル、データベース レベル、またはオブジェクト レベル) を取得しようとするスコープ (現在サポートされているオブジェクトはキューだけです)。 最終的に、このスコープは対象データベースで作成されたイベント通知の種類を決定します。 このプロセスは、イベント通知登録と呼ばれます。

  • データベース、スキーマ、オブジェクトのうちの適切な登録場所。

WMI Provider for Server Events では、ボトムアップの優先適合アルゴリズムを使用して、基になる EVENT NOTIFICATIONオブジェクトに対して可能な限り狭いスコープを生成します。 このアルゴリズムは、SQL Server のインスタンスと WMI ホスト プロセスの間のサーバーとネットワーク トラフィックの内部アクティビティを最小限に抑えようとします。 プロバイダーは、句でFROM指定されたevent_typeと句の条件をWHERE調べ、基になるEVENT NOTIFICATIONスコープを可能な限り狭く登録しようとします。 プロバイダーが最も狭いスコープで登録できない場合は、登録が最終的に成功するまで、連続して上位のスコープで登録を試みます。 最も高いスコープ (サーバーレベル) に到達して失敗した場合、エラーがコンシューマーに返されます。

たとえば、句でWHERE指定した場合DatabaseName='AdventureWorks2022'、プロバイダーはデータベースにイベント通知をAdventureWorks2022登録しようとします。 AdventureWorks2022 データベースが存在し、呼び出し側クライアントが、AdventureWorks2022 のイベント通知を作成するために必要な権限を持っている場合、登録は正常に完了します。 それ以外の場合は、イベント通知をサーバー レベルで登録しようとします。 WMI クライアントが必要な権限を持っている場合、登録は正常に終了します。 ただし、このシナリオでは、データベースが作成されるまでイベントはクライアントに AdventureWorks2022 返されません。

where_conditionフィルターとして機能して、クエリを特定のデータベース、スキーマ、またはオブジェクトに制限することもできます。 たとえば、次の WQL クエリを考えてみましょう。

SELECT * FROM ALTER_TABLE
WHERE DatabaseName = 'AdventureWorks2022' AND SchemaName = 'Sales'
    AND ObjectType='Table' AND ObjectName = 'SalesOrderDetail'

登録プロセスの結果によっては、この WQL クエリがデータベース レベルまたはサーバー レベルで登録される場合があります。 ただし、サーバー レベルで登録されている場合でも、プロバイダーは最終的にテーブルに適用されないイベントをSales.SalesOrderDetailフィルター処理ALTER_TABLEします。 つまり、プロバイダーは、この特定のテーブル上で発生した ALTER_TABLE イベントのプロパティのみを返します。

このような DatabaseName='AW1' OR DatabaseName='AW2' 複合式が指定されている場合、2 つの個別のイベント通知ではなく、サーバー スコープで 1 つのイベント通知を登録しようとします。 呼び出し側クライアントが権限を持っている場合、登録は正常に終了します。

句でWHEREすべて指定されている場合SchemaName='X' AND ObjectType='Y' AND ObjectName='Z'は、スキーマX内のオブジェクトZに直接イベント通知を登録しようとします。 クライアントが権限を持っている場合、登録は正常に終了します。 現在、オブジェクト レベルのイベントはキューでのみサポートされ、event_typeに対QUEUE_ACTIVATIONしてのみサポートされています。

特定のスコープですべてのイベントを照会できるわけではありません。 たとえば、Lock_Deadlockなどのトレース イベントまたはトレース イベント グループ TRC_LOCKSに対する WQL クエリは、サーバー レベルでのみ登録できます。 同様に CREATE_ENDPOINT 、イベントと DDL_ENDPOINT_EVENTS イベント グループは、サーバー レベルでのみ登録することもできます。 イベントを登録するための適切なスコープの詳細については、「イベント通知の設計」を参照してください。 event_typeをサーバー レベルでのみ登録できる WQL クエリを登録しようとすると、常にサーバー レベルで行われます。 WMI クライアントが権限を持っている場合、登録は正常に終了します。 それ以外の場合は、クライアントにエラーが返されます。 ただし、場合によっては、イベントに対応する WHERE プロパティに基づいて、サーバー レベルのイベントのフィルターとして句を引き続き使用できます。 たとえば、多くのトレース イベントには、 DatabaseName 句で WHERE フィルターとして使用できるプロパティがあります。

サーバー スコープのイベント通知はデータベースにmaster作成され、sys.server_event_notifications カタログ ビューを使用してメタデータを照会できます。

データベース スコープまたはオブジェクト スコープのイベント通知は、指定されたデータベースに作成され、sys.event_notifications カタログ ビューを使用してメタデータを照会できます。 (カタログ ビューのプレフィックスには、対応するデータベース名を使用する必要があります)。

この記事には AdventureWorks2022 サンプル データベースが必要です。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクトのホーム ページからダウンロードできます。

A. サーバー スコープでのイベントのクエリ

次の WQL クエリは、SQL Server のインスタンスで発生するすべての SERVER_MEMORY_CHANGE トレース イベントのすべてのイベント プロパティを取得します。

SELECT * FROM SERVER_MEMORY_CHANGE

B. データベース スコープでのイベントのクエリ

次の WQL クエリは、AdventureWorks2022 データベース内で発生し、DDL_DATABASE_LEVEL_EVENTS イベント グループに存在するイベントの特定のイベント プロパティを取得します。

SELECT SPID, SQLInstance, DatabaseName FROM DDL_DATABASE_LEVEL_EVENTS
WHERE DatabaseName = 'AdventureWorks2022'

C: スキーマとオブジェクトによるフィルター処理を行って、データベース スコープでイベントのクエリを実行する

次のクエリは、テーブル ALTER_TABLE 上で発生する Sales.SalesOrderDetail イベントのイベント プロパティを取得します。

SELECT * FROM ALTER_TABLE
WHERE DatabaseName = 'AdventureWorks2022' AND SchemaName = 'Sales'
    AND ObjectType='Table' AND ObjectName = 'SalesOrderDetail'