将 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
子句中的参数可以为可对其创建事件通知的任何有效事件。 SELECT
和 WHERE
子句中的参数可以指定与某一事件或其父事件关联的任何事件属性。 有关有效事件和事件属性的列表,请参阅事件通知(数据库引擎)。
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 ] |*
事件的一个属性。 示例包括 PostTime
、SPID
和 LoginName
。 查找 WMI Provider for Server Events 类和属性中列出的每个事件,以确定它保存的属性。 例如,DDL_DATABASE_LEVEL_EVENTS 事件具有 DatabaseName
和 UserName
属性。 事件还从其父事件继承 SQLInstance
、LoginName
、PostTime
、SPID
和 ComputerName
属性。
, ...n
指示 可以多次查询event_property ,用逗号分隔。
*
指定对与事件关联的所有属性进行查询。
event_type
可以创建事件通知的任何事件。 有关可用事件的列表,请参阅 适用于服务器事件类和属性的 WMI 提供程序。 事件类型名称对应于使用手动创建事件通知CREATE EVENT NOTIFICATION
时可以指定的相同event_type | event_group。 事件类型的示例包括CREATE_TABLE
、LOCK_DEADLOCK
和DDL_USER_EVENTS
TRC_DATABASE
。
注意
执行 DDL 式操作的某些系统存储过程也可以激发事件通知。 测试您的事件通知以确定它们是否响应运行的系统存储过程。 例如, CREATE TYPE
语句和 sp_addtype
存储过程都会触发在事件上 CREATE_TYPE
创建的事件通知。 但是, sp_rename
存储过程不会触发任何事件通知。 有关详细信息,请参阅 DDL 事件。
where_condition
子 WHERE
句查询谓词,由 event_property 名称和逻辑和比较运算符组成。 where_condition确定在目标数据库中注册相应事件通知的范围。 它还可以充当筛选器来定位要从中查询 event_type的特定架构或对象。 有关详细信息,请参阅“ 备注 ”部分。
只有 =
操作数可与 DatabaseName
、SchemaName
和 ObjectName
一起使用。 其他表达式不能用于这些事件属性。
注解
WMI Provider for Server Events 语法的where_condition确定以下内容:
提供程序尝试检索指定 event_type的范围:服务器级别、数据库级别或对象级别(当前唯一支持的对象是队列)。 最后,此范围用于确定在目标数据库中创建的事件通知的类型。 这个过程称为事件通知注册。
要在其上进行注册的数据库、架构和对象(视具体情况而定)。
用于服务器事件的 WMI 提供程序使用自下而上、第一拟合的算法为基础 EVENT NOTIFICATION
生成最窄的范围。 该算法尝试最大程度地减少服务器上的内部活动以及 SQL Server 实例与 WMI 主机进程之间的网络流量。 提供程序检查子句中指定的FROM
event_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_ACTIVATION
event_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 代码示例使用 AdventureWorks2022
或 AdventureWorksDW2022
示例数据库,可从 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'