How to create Trigger for all tables in a bank automatically?

Asked

Viewed 782 times

5

Example scenario

I have a database with 1,000 tables.

One table call log.


Goal

I would like to create a Trigger "standard" in each of these tables, automatically.

That one Trigger, whenever there is any change (Insert, update, delete) it runs a insert on the table log, with a timestamp and the nome of the table in question (extra would be the name of the column(s))).

In the same context, I would like to know if there is a way view all existing triggers in a database.

1 answer

5


I believe that in this way you will be able to achieve what you want:

CREATE TABLE [log]
(
        Id          UNIQUEIDENTIFIER    CONSTRAINT log_Id_DF        DEFAULT(NEWID())    NOT NULL
    ,   [Timestamp] DATETIME            CONSTRAINT log_Timestamp_DF DEFAULT(GETDATE())  NOT NULL
    ,   Tabela      NVARCHAR(255)       NOT NULL
    ,   Colunas     NVARCHAR(MAX)       NOT NULL
    ,   PRIMARY KEY (Id)
)

DECLARE @SQL AS NVARCHAR(MAX) = ''

DECLARE cur_trigger CURSOR FOR
    SELECT      '
                    CREATE TRIGGER [' + TABLE_SCHEMA + '].[tr' + TABLE_NAME + '_auto]
                    ON [' + TABLE_SCHEMA + '].[' + TABLE_NAME + '] FOR INSERT, UPDATE, DELETE AS
                    BEGIN
                        DECLARE @IdTabela   INT
                        DECLARE @Tabela     NVARCHAR(255)
                        DECLARE @Colunas    NVARCHAR(MAX)

                        SELECT  @Tabela = object_name(parent_id) 
                        FROM    sys.triggers 
                        WHERE   object_id = @@PROCID

                        SELECT  @IdTabela   = T.id
                        FROM    sysobjects P JOIN sysobjects T ON P.parent_obj = T.id 
                        WHERE   P.id = @@PROCID

                        SELECT  @Colunas = ISNULL(@Colunas + '', '', '''') + name 
                        FROM    syscolumns 
                        WHERE   id = @IdTabela   
                            AND CONVERT(VARBINARY, REVERSE(COLUMNS_UPDATED())) & POWER(CONVERT(BIGINT, 2), colorder - 1) > 0

                        INSERT INTO [log](Tabela, Colunas) VALUES(@Tabela, @Colunas)
                    END
                '
    FROM        INFORMATION_SCHEMA.TABLES
    WHERE       TABLE_TYPE = 'BASE TABLE'
            AND TABLE_NAME <> 'log'
    ORDER BY    TABLE_NAME

OPEN cur_trigger

FETCH NEXT FROM cur_trigger INTO @SQL

WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC(@SQL)
    FETCH NEXT FROM cur_trigger INTO @SQL   
END

CLOSE cur_trigger
DEALLOCATE cur_trigger

Basically uses dynamic SQL to build the trigger and then all you have to do is execute.
In terms of syntax is correct, but has not been tested in your scenario.

Some ideas taken from Soen: SQL Server Update Trigger, Get Only modified Fields


To consult all the triggers from a database, you can do the following:

SELECT      *
FROM        sys.triggers  
WHERE       [type] = 'TR'
ORDER BY    [name]

  • John, I’ll test as soon as I can and get back to you! Only one case that Woss raised, the table "log" can not enter the creation of triggers, if it would not become eternal loop... rs

  • And it doesn’t come in @Rbz, it’s before the CURSOR :). Anyway I just put it to be a 100% functional example, but of course, the table is later created as you want.

  • Oops! Top! I need to look very calmly to digest all this! kkkk From what I was seeing, it will list up the changed columns?

  • Yes, that’s it! All you need to do is test it in your database to confirm that triggers are well created and are executed correctly.

  • There is a mistake in the creation of the log, in the type... but I will test in general and I tell you. Thanks teacher!

  • You’re right, a DEFAULT CONSTRAINT in columns of the type TIMESTAMP. Edited response!

  • John, I excluded everything, I executed again, and the table log is generating Tigger yes...

  • But the table itself is supposed to, log, generate records in log? 'Cause if you don’t, we’re gonna have to put a clause in to prevent that.

  • But then goes into infinite loop João. If Trigger inserts in log any DML, she would always "auto-fire". I think a AND TABLE_NAME <> 'log' would solve, right?

  • Right, yes! I’ll edit the answer to include this scenario.

  • Working perfectly!

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.