【问题标题】:SQL Server: using dm_exec_describe_first_result_set with table variable fires CREATE_TABLE triggerSQL Server:使用 dm_exec_describe_first_result_set 和表变量触发 CREATE_TABLE 触发器
【发布时间】:2019-09-19 11:29:11
【问题描述】:

我尝试将 sys.dm_exec_describe_first_result_set 与包含表变量的查询一起使用来描述查询的列。 但是在此查询中声明表变量会导致事件 AFTER CREATE_TABLE 的 DATABASE 触发器激活,该事件包含使用临时表调用存储过程。

通常声明此触发器不激活的表变量。一些想法为什么会为表变量激活触发器?

CREATE PROCEDURE SP1 AS
BEGIN 
CREATE TABLE #A(b int)
INSERT INTO #A(b) VALUES(1)
DROP TABLE #A
END
GO

CREATE TRIGGER [CreateObjectDatabaseTrigger]
ON DATABASE 
AFTER 
    CREATE_TABLE
AS 
BEGIN
EXEC SP1
END
GO
ENABLE TRIGGER [CreateObjectDatabaseTrigger] ON DATABASE

DECLARE @SqlQuery NVARCHAR(MAX) = N'DECLARE @A TABLE (b int) SELECT * FROM @A'

SELECT error_message, name 
FROM 
sys.dm_exec_describe_first_result_set
(@SqlQuery, NULL, 0)

启用触发器的结果:无法确定元数据,因为过程“SP1”中的语句“INSERT INTO #A(b) VALUES(1)”使用临时表。

【问题讨论】:

    标签: sql sql-server triggers


    【解决方案1】:

    触发器不应将结果集返回给客户端。这样做是不推荐的行为,并将根据documentation 从 SQL Server 的未来版本中删除。

    在这种情况下,使用PRINT 返回信息性消息而不是结果集。这种做法的副作用是sys.dm_exec_describe_first_result_set 将返回所需的元数据:

    CREATE TRIGGER [CreateObjectDatabaseTrigger]
    ON DATABASE 
    AFTER 
        CREATE_TABLE
    AS 
    BEGIN
    PRINT 'Trigger activated';
    END
    GO
    ENABLE TRIGGER [CreateObjectDatabaseTrigger] ON DATABASE;
    
    DECLARE @SqlQuery NVARCHAR(MAX) = N'DECLARE @A TABLE (b int) SELECT * FROM @A';
    
    SELECT error_message, name 
    FROM sys.dm_exec_describe_first_result_set
    (@SqlQuery, NULL, 0);
    

    【讨论】:

    • 感谢您的回答。触发器中的 SELECT 语句仅用于说明。我的真实触发器包含调用存储过程,它使用临时表 (CREATE TABLE #A),在 dm_exec_describe_first_result_set 中不受支持(无法确定元数据,因为语句 'SELECT * FROM #A' 使用临时表。元数据发现仅在分析单语句批处理时支持临时表。)。所以我想避免触发激活。
    • @Martin,那么您应该编辑您的问题以添加演示您的实际问题的代码。
    猜你喜欢
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多