如何在 SQL 服务器扩展事件中单独跟踪游标语句?

How to track cursor statements separately in SQL Server extended events?

我想使用扩展事件将语句跟踪到 SQL 服务器游标,但在 Internet 上找到的所有解决方案都不起作用 - 例如,this.

测试代码:

DECLARE @objectId int;

DECLARE cur CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY
FOR
SELECT TOP(3) object_id
FROM sys.tables AS t
ORDER BY object_id;

OPEN cur;
FETCH NEXT FROM cur INTO @objectId;
WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRAN;
    SELECT @objectId AS object_id;
    WAITFOR DELAY '00:00:01';
    COMMIT;
    FETCH NEXT FROM cur INTO @objectId;
END;
CLOSE cur;
DEALLOCATE cur;

如果您希望使用扩展事件跟踪 SQL 服务器游标及其内部语句,您可以从库中选择这些事件:

  1. sqlserver.cursor_manager_* 事件
    使用它们捕获 TSQL Cursor

  2. sqlserver.cursor_* 事件
    使用它们捕获 API 光标

在您的示例中,您使用的是 TSQL 光标。


这是一个示例扩展事件会话脚本,用于捕获 TSQL Cursor open/close 事件。
它将捕获由测试代码中声明的 TSQL 游标触发的事件。

注意: 我还必须捕获事件 sqlserver.sql_statement_completed,在order 从游标中执行语句。

CREATE EVENT SESSION [Track_tsql_cursor] ON SERVER 
ADD EVENT sqlserver.cursor_manager_cursor_end( 
    ACTION( 
        sqlserver.client_app_name, 
        sqlserver.database_name, 
        sqlserver.is_system, 
        sqlserver.session_id, 
        sqlserver.sql_text) 
    WHERE ([sqlserver].[database_name]=N'...') 
), 
ADD EVENT sqlserver.cursor_manager_cursor_begin( 
    ACTION( 
        sqlserver.client_app_name, 
        sqlserver.database_name, 
        sqlserver.is_system, 
        sqlserver.query_hash, 
        sqlserver.session_id, 
        sqlserver.sql_text) 
    WHERE ([sqlserver].[database_name]=N'...') 
), 
ADD EVENT sqlserver.sql_statement_completed( 
    ACTION( 
        sqlserver.client_app_name, 
        sqlserver.database_name, 
        sqlserver.is_system, 
        sqlserver.query_hash, 
        sqlserver.session_id, 
        sqlserver.sql_text) 
    WHERE ([sqlserver].[database_name]=N'...') 
) 
WITH ( 
    MAX_MEMORY=16384 KB, 
    MAX_DISPATCH_LATENCY=10 SECONDS, 
    TRACK_CAUSALITY=ON 
); 
GO 

以下是您的测试查询结果(在 SQL Server 2019 和 2014 上测试):