我可以循环为所有表创建触发器吗?

时间:2019-04-11 08:09:05

标签: sql-server

我有这样的脚本,从理论上讲,该脚本使我可以为数据库中的每个表创建相同的触发器:

DECLARE @insertTriggers VARCHAR(MAX) = '';
SELECT @insertTriggers = @insertTriggers1 + *Some Trigger creation code ending with 'GO'"
FROM INFORMATION_SCHEMA.TABLES
EXEC(@insertTriggers);

当我使用PRINT并将其复制到其他查询时,它可以工作,因为我可以用关键字GO分隔CREATE TRIGGERS。在这里不起作用。我能做什么?我必须为每个触发器分别编写一个代码吗?

2 个答案:

答案 0 :(得分:0)

根据我的评论,我出于审计目的开发了此SP,但它最初可能不适用于您,但是如果您更改它,我相信它将为您提供帮助。

否则,请更改您对触发器需要执行的操作的问题,然后我将更改答案以为您工作...

if exists(select 1 from sysobjects where name = 'kv_sp_dbAudits_tr_AW')
drop procedure kv_sp_dbAudits_tr_AW
go

set ansi_nulls on
go

set quoted_identifier on
go

create procedure kv_sp_dbAudits_tr_AW(@tablename varchar(150),@switch bit)
as

BEGIN

if exists(select name from sysobjects where name = 'TempTableTriggers')
drop table TempTableTriggers;

create table TempTableTriggers (tablename varchar(100),columns varchar(max),columnvars varchar(max),columnvarst varchar(max),columnalloc varchar(max))

declare @query          varchar(max)
,       @loop           int
,       @dbname         varchar(50) =   (select db_name())+'_Audit'
,       @table          varchar(100)
,       @tableau        varchar(100)
,       @trigger        varchar(100)
,       @column         varchar(max)
,       @columnvars     varchar(max)
,       @columnvarst    varchar(max)
,       @columnalloc    varchar(max)
,       @crlf           char(2)         =   char(13)+char(10)

        declare @Tables table
        (   id  int identity primary key
        ,   TableName   varchar(100)
        ,   TriggerName varchar(100)
        ,   Columns     varchar(max))

    if @tablename like ''+'%'+''
        set @tablename  =   @tablename
    else
        set @tablename  =   ''+@tablename+''

    set @trigger = @tablename+'_Audit_kvtr_AW'

    begin
        if  @switch = 1
            begin
                if exists(select name from sysobjects where name = @trigger)
                    begin
                        set @tablename  =   (select name from sysobjects where name = @tablename)
                        set @query      =   @crlf
                        set @query      =   @query + @crlf
                        set @query      =   @query + @crlf
                        set @query      =   @query + @crlf
                        set @query      =   @query + replicate('-',80)+@crlf
                        set @query      =   @query + @crlf
                        set @query      =   @query + 'The audit trigger "'+@tablename+'_Audit_kvtr_AW'+'" already exists!'
                        print (@query)
                    end
                else
                    begin
                        if @tablename = 'all'

                            insert into @Tables
                            (   TableName   )
                            select
                            name
                            from    sysobjects
                            where   xtype   =   'u'
                            and name not like   '%audit%'
                            and name <>         'TempTableTriggers'
                            order by name

                        else

                            insert into @Tables
                            (   TableName   )
                            select
                            name
                            from    sysobjects
                            where   xtype   =   'u'
                            and name not like   '%audit%'
                            and name <>         'TempTableTriggers'
                            and name = @tablename
                            order by name

                        select @loop = min(id) from @Tables
                        while @loop is not null

                        begin
                                begin
                                    set @query  =   '   declare @columns        varchar(max)

                                                    select @columns = stuff((select '','' + char(10)+quotename(Column_Name)
                                                    from information_schema.columns
                                                    where   table_name = '''+(select TableName from @Tables where id = @loop)+'''
                                                    and Column_Name <> ''cAllocs''
                                                    and data_type not in (''text'',''image'',''ntext'')
                                                    group by column_name, data_type, character_maximum_length, ordinal_position
                                                    order by ordinal_position
                                                    for xml path(''''), type).value(''.'', ''nvarchar(max)''),1,1,'''')

                                                    insert into TempTableTriggers   (tablename,columns)
                                                    select  distinct
                                                        table_name
                                                    ,   @columns
                                                    from information_schema.columns
                                                    where   table_name = '''+(select TableName from @Tables where id = @loop)+''''
                                    exec (@query)
                                end
                            select @loop = min(id) from @Tables where id>@loop
                        end

                        insert into @Tables
                        (TriggerName,TableName,Columns)
                        select
                        TableName,TableName,columns
                        from    TempTableTriggers

                        select @loop = min(id) from @Tables
                        while @loop is not null

                        begin
                                begin
                                    select  @trigger        =   TriggerName+'_Audit_kvtr_AW'
                                    ,       @tableau        =   TableName+'_Audit'
                                    ,       @table          =   TableName
                                    ,       @column         =   Columns
                                    from                        @Tables
                                    where   id              =   @loop

                                        set @query  =           'create trigger '+@trigger+' on '+@table+@crlf
                                        set @query  =   @query+ 'with encryption'+@crlf
                                        set @query  =   @query+ 'after insert, update, delete'+@crlf
                                        set @query  =   @query+ 'as'+@crlf
                                        set @query  =   @query+ '/***********************************************************************************************************************************'+@crlf
                                        set @query  =   @query+ 'Description        :   To insert any change made in '+@table+' into '+@dbname+'.dbo.'+@table+'_Audit'+@crlf
                                        set @query  =   @query+ 'Author         :   Attie Wagner'+@crlf
                                        set @query  =   @query+ 'Creation Date  :   30  October 2018'+@crlf
                                        set @query  =   @query+ 'Modified By        :   Attie Wagner'+@crlf
                                        set @query  =   @query+ 'Modified Date  :   28  January 2019'+@crlf
                                        set @query  =   @query+ '************************************************************************************************************************************/'+@crlf
                                        set @query  =   @query+ @crlf
                                        set @query  =   @query+ 'begin'+@crlf
                                        set @query  =   @query+ @crlf
                                        set @query  =   @query+ 'set nocount on'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'if (select trigger_nestlevel(object_id('''+@trigger+'''))) > 1'+@crlf
                                        set @query  =   @query+ 'return'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'declare @inserted varchar(15) = '''''+@crlf
                                        set @query  =   @query+ 'declare @deleted varchar(15) = '''''+@crlf
                                        set @query  =   @query+ 'declare @updated varchar(15) = '''''+@crlf
                                        set @query  =   @query+ 'declare @action varchar(15) = '''''+@crlf
                                        set @query  =   @query+ 'if((exists(select * from inserted)) and (exists(select * from deleted)))'+@crlf
                                        set @query  =   @query+ '   set @updated = ''updated'''+@crlf
                                        set @query  =   @query+ 'else'+@crlf
                                        set @query  =   @query+ 'if(exists(select * from inserted))'+@crlf
                                        set @query  =   @query+ '   set @inserted = ''new'''+@crlf
                                        set @query  =   @query+ 'else'+@crlf
                                        set @query  =   @query+ 'if(exists(select * from deleted))'+@crlf
                                        set @query  =   @query+ '   set @deleted = ''deleted'''+@crlf
                                        set @query  =   @query+ 'set @action = (select case when @inserted = ''new'' then ''new'' when @updated = ''updated'' then ''updated'' when @deleted = ''deleted'' then ''deleted'' else '''' end)'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'declare @kvAgent varchar(100)  =   (select cAgentName from _rtblAgents where idAgents  =   [dbo]._efnAgentIDFromConnection(''dbo''))'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'if @action in (''new'',''updated'')'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'begin'+@crlf
                                        set @query  =   @query+     'insert into ['+@dbname+'].dbo.'+@tableau+' ('+@column+','+@crlf+'kvUsername,'+@crlf+'kvDTStamp,'+@crlf+'kvAction)'+@crlf
                                        set @query  =   @query+ @crlf
                                        set @query  =   @query+     'select '+@column+','+@crlf+'@kvAgent,'+@crlf+'getdate(),'+@crlf+'@action'+@crlf
                                        set @query  =   @query+     'from inserted'+@crlf
                                        set @query  =   @query+ 'end;'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'if @action = ''deleted'''+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'begin'+@crlf
                                        set @query  =   @query+     'insert into ['+@dbname+'].dbo.'+@tableau+' ('+@column+','+@crlf+'kvUsername,'+@crlf+'kvDTStamp,'+@crlf+'kvAction)'+@crlf
                                        set @query  =   @query+ @crlf
                                        set @query  =   @query+     'select '+@column+','+@crlf+'@kvAgent,'+@crlf+'getdate(),'+@crlf+'@action'+@crlf
                                        set @query  =   @query+     'from deleted'+@crlf
                                        set @query  =   @query+ 'end;'+@crlf
                                        set @query  =   @query+ @crlf

                                        set @query  =   @query+ 'begin'+@crlf
                                        set @query  =   @query+     'delete '+quotename(@dbname)+'.dbo.'+@table+'_Audit'+@crlf
                                        set @query  =   @query+     'where  datediff(month,kvDTStamp,getdate()) > 12'+@crlf
                                        set @query  =   @query+ 'end;'+@crlf
                                        set @query  =   @query+ @crlf
                                        set @query  =   @query+ 'end;'+@crlf

                                    exec (@query)
                                end
                            select @loop = min(id) from @Tables where id>@loop
                        end
                    end

                drop table TempTableTriggers;
            end
        else
            begin
                if @tablename = 'all'

                    insert into @Tables
                    (   TriggerName )
                    select name from sysobjects
                    where xtype = 'tr'
                    and name like   '%_Audit_kvtr_AW'
                    order by name

                else

                    insert into @Tables
                    (   TriggerName )
                    select name from sysobjects
                    where xtype = 'tr'
                    and name like   '%_Audit_kvtr_AW'
                    and name = @tablename+'_Audit_kvtr_AW'
                    order by name

                select @loop = min(id) from @Tables
                while @loop is not null

                begin
                        begin
                            set @trigger    =   (select TriggerName from @Tables where id = @loop)
                            set @query      =   'if exists(select name from sysobjects where name = '''+@trigger+''')'+@crlf
                            set @query      =   @query+'drop trigger '+@trigger
                            exec (@query)
                        end
                    select @loop = min(id) from @Tables where id>@loop
                end
            end
    end
END;

答案 1 :(得分:0)

您可以使用它作为模板来创建触发器。

DECLARE @TriggerTemplate NVARCHAR(MAX)
DECLARE @TriggerNameTemplate NVARCHAR(250)
DECLARE @Tables TABLE (ID INT IDENTITY, TableName VARCHAR(100))
INSERT @Tables 
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.Tables WHERE TABLE_TYPE = 'BASE TABLE'

DECLARE @ID INT, @TableName VARCHAR(100)
DECLARE @SQL NVARCHAR(MAX), @TriggerName NVARCHAR(250)
WHILE EXISTS (SELECT 1 FROM @Tables)
BEGIN
    SELECT TOP 1 @ID = ID, @TableName = TableName FROM @Tables
    SET @TriggerName = REPLACE(@TriggerNameTemplate,'#TableName#', QUOTENAME(@TableName))
    IF EXISTS(SELECT * FROM sys.triggers WHERE name = @TriggerName)
    BEGIN
        SET @SQL = 'DROP TRIGGER ' + @TriggerName
        EXEC (@SQL)
    END
    SET @SQL = REPLACE(@TriggerTemplate,'#TableName#', QUOTENAME(@TableName))

    EXEC(@SQL)

    DELETE @Tables WHERE ID = @ID
END