将 WQL 与用于服务器事件的 WMI 提供程序配合使用

适用范围:SQL Server

管理应用程序通过发出 WMI 查询语言(WQL)语句,使用 WMI 提供程序访问服务器事件的 SQL Server 事件。 WQL 是结构化查询语言 (SQL) 的简化子集,它还包含一些特定于 WMI 的扩展。 在使用 WQL 时,应用程序针对 SQL Server 的特定实例、数据库或数据库对象(当前唯一支持的对象是队列)检索事件类型。 用于服务器事件的 WMI 提供程序将查询转换为事件通知,该通知是在目标数据库中为数据库范围或对象范围事件通知创建的事件通知,或者在服务器范围事件通知的 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 子句中的参数可以为可对其创建事件通知的任何有效事件。 SELECTWHERE 子句中的参数可以指定与某一事件或其父事件关联的任何事件属性。 有关有效事件和事件属性的列表,请参阅事件通知(数据库引擎)。

WMI Provider for Server Events 显式支持以下 WQL 语法。 可以指定其他 WQL 语法,但它不特定于此提供程序,而是由 WMI 主机服务分析。 有关 WMI 查询语言的详细信息,请参阅 Microsoft Developer Network (MSDN) 上的 WQL 文档。

语法

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

参数

event_property [ , ...n ] |*

事件的一个属性。 示例包括 PostTimeSPIDLoginName。 查找 WMI Provider for Server Events 类和属性中列出的每个事件,以确定它保存的属性。 例如,DDL_DATABASE_LEVEL_EVENTS 事件具有 DatabaseNameUserName 属性。 事件还从其父事件继承 SQLInstanceLoginNamePostTimeSPIDComputerName 属性。

  • ...n

    指示 可以多次查询event_property ,用逗号分隔。

  • *

    指定对与事件关联的所有属性进行查询。

event_type

可以创建事件通知的任何事件。 有关可用事件的列表,请参阅 适用于服务器事件类和属性的 WMI 提供程序。 事件类型名称对应于使用手动创建事件通知CREATE EVENT NOTIFICATION时可以指定的相同event_type | event_group。 事件类型的示例包括CREATE_TABLELOCK_DEADLOCKDDL_USER_EVENTSTRC_DATABASE

注意

执行 DDL 式操作的某些系统存储过程也可以激发事件通知。 测试您的事件通知以确定它们是否响应运行的系统存储过程。 例如, CREATE TYPE 语句和 sp_addtype 存储过程都会触发在事件上 CREATE_TYPE 创建的事件通知。 但是, sp_rename 存储过程不会触发任何事件通知。 有关详细信息,请参阅 DDL 事件

where_condition

WHERE 句查询谓词,由 event_property 名称和逻辑和比较运算符组成。 where_condition确定在目标数据库中注册相应事件通知的范围。 它还可以充当筛选器来定位要从中查询 event_type的特定架构或对象。 有关详细信息,请参阅“ 备注 ”部分。

只有 = 操作数可与 DatabaseNameSchemaNameObjectName 一起使用。 其他表达式不能用于这些事件属性。

注解

WMI Provider for Server Events 语法的where_condition确定以下内容:

  • 提供程序尝试检索指定 event_type的范围:服务器级别、数据库级别或对象级别(当前唯一支持的对象是队列)。 最后,此范围用于确定在目标数据库中创建的事件通知的类型。 这个过程称为事件通知注册。

  • 要在其上进行注册的数据库、架构和对象(视具体情况而定)。

用于服务器事件的 WMI 提供程序使用自下而上、第一拟合的算法为基础 EVENT NOTIFICATION生成最窄的范围。 该算法尝试最大程度地减少服务器上的内部活动以及 SQL Server 实例与 WMI 主机进程之间的网络流量。 提供程序检查子句中指定的FROMevent_type以及子句中的WHERE条件,并尝试将基础EVENT NOTIFICATION注册到尽可能窄的范围。 如果提供程序无法在最窄的范围内注册,它会尝试在连续更高的范围注册,直到注册最终成功。 如果它达到服务器级别的最大范围且失败,则它将向使用者返回一个错误。

例如,如果在 DatabaseName='AdventureWorks2022' 子句中 WHERE 指定,提供程序将尝试在 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' ,则尝试在服务器范围注册单个事件通知,而不是两个单独的事件通知。 如果调用客户端拥有权限,则注册成功。

如果在SchemaName='X' AND ObjectType='Y' AND ObjectName='Z'子句中WHERE全部指定,则尝试直接在架构X中的对象Z上注册事件通知。 如果客户端拥有权限,则注册成功。 目前,对象级事件仅在队列上受支持,并且仅支持QUEUE_ACTIVATIONevent_type

并非所有事件都可以在任何特定范围内查询。 例如,对跟踪事件(例如Lock_Deadlock)或跟踪事件组(例如 TRC_LOCKS)的 WQL 查询只能在服务器级别注册。 同样, CREATE_ENDPOINT 事件和 DDL_ENDPOINT_EVENTS 事件组也可以仅在服务器级别注册。 有关注册事件的适当范围的详细信息,请参阅 “设计事件通知”。 尝试注册一个 WQL 查询,其 event_type 只能在服务器级别注册,始终在服务器级别进行注册。 如果 WMI 客户端拥有权限,则注册成功。 否则,将向客户端返回一个错误。 但是,在某些情况下,仍 WHERE 可以根据与事件对应的属性将子句用作服务器级事件的筛选器。 例如,许多跟踪事件都有一个 DatabaseName 属性,可在子 WHERE 句中用作筛选器。

服务器范围内的事件通知是在master数据库中创建的,可以使用sys.server_event_notifications目录视图查询元数据

数据库范围或对象范围内的事件通知是在指定的数据库中创建的,可以使用sys.event_notifications目录视图查询元数据。 (您必须为目录视图加上对应的数据库名前缀。)

示例

本文中的 Transact-SQL 代码示例使用 AdventureWorks2022AdventureWorksDW2022 示例数据库,可从 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'