T-SQL使用DDLTrigger修改过程定义

时间:2014-10-22 15:17:57

标签: sql-server tsql

我的数据库上有一个数据库触发器,用于在创建/更改过程时使用EventData审核过程。

我想知道是否有任何方法可以通过“SlipStreaming”修改过程定义将注释行修改为过程定义的结尾?无需:禁用触发器,从EVENTDATA中的DDL定义创建动态SQL字符串,将相关的注释行附加到动态SQL,执行Dynimc SQL以更新proc,然后再次启用触发器......

任何想法?

1 个答案:

答案 0 :(得分:0)

不需要禁用触发器,因为SQL Server默认情况下不允许触发器触发自身(这由RECURSIVE_TRIGGERS数据库选项控制,默认情况下该选项处于关闭状态。因此,您可以从触发器进行DDL修改而不必担心触发自己 - 但您要做的是验证您是否没有被另一个触发器触发,因为这可能导致循环。为此,请使用TRIGGER_NESTLEVEL

以下是边缘有点粗糙,但它应该让你开始。特别是,您可能希望自定义注释。此外,检测修改标记是否已经存在是不确定的(但如果您不介意堆叠注释,则可能不需要它)。您可以考虑在存储过程中添加/更改extended property,而不是以文本方式修改它。

AFTER CREATE_PROCEDURE, ALTER_PROCEDURE
AS
BEGIN
    SET ARITHABORT ON;
    SET NOCOUNT ON;
    IF TRIGGER_NESTLEVEL() > 1 RETURN;

    PRINT CONVERT(NVARCHAR(MAX), EVENTDATA());

    DECLARE @DatabaseName NVARCHAR(128);
    SET @DatabaseName = EVENTDATA().value(
        '(/EVENT_INSTANCE/DatabaseName)[1]', 'NVARCHAR(128)'
    );
    DECLARE @Schema NVARCHAR(128);
    SET @Schema = EVENTDATA().value(
        '(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(128)'
    );
    DECLARE @Name NVARCHAR(128);
    SET @Name = EVENTDATA().value(
        '(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(128)'
    );

    DECLARE @Definition NVARCHAR(MAX);
    SELECT @Definition = 
        OBJECT_DEFINITION(
            OBJECT_ID(
                QUOTENAME(@DatabaseName) + '.' + 
                QUOTENAME(@Schema) + '.' + 
                QUOTENAME(@Name),
                'P'
            )
        )
    ;
    SELECT @Definition = STUFF(
        @Definition, 
        CHARINDEX('CREATE', @Definition), 
        LEN('CREATE'), 
        'ALTER'
    );

    IF @Definition NOT LIKE '%--Hacked by Chinese' BEGIN;
        SET @Definition += CHAR(13) + CHAR(10) + '--Hacked by Chinese';
        EXEC (@Definition);
    END;
END;
GO
ENABLE TRIGGER [TR_TweakStoredProcedures] ON DATABASE