Home Forums SQL Server 2005 T-SQL (SS2K5) Trigger that uses a Parameter with Inserted/Deleted RE: Trigger that uses a Parameter with Inserted/Deleted

  • if you think you need a cursor in a trigger, you're always, and i mean ALWAYS, looking at the problem wrong.

    one of the new feature sin SQL2005 is the COLUMNS_UPDATED function, where you can say, audit changes only of columns 2,4,5 or 6 in your table have been changed.

    here's an example to play with:

    CREATE TABLE MYADDRESSES(

    EMPNO INT IDENTITY(1,1) PRIMARY KEY,

    ENAME VARCHAR(100), --column 2 will not track changes

    ADDR1 VARCHAR(100),

    ADDR2 VARCHAR(100),

    CITY VARCHAR(100),

    STATECODE VARCHAR(2),

    ZIPCODE VARCHAR(100),

    PHONE VARCHAR(20),

    MOREDATA VARCHAR(100)) --column 9 will not track changes

    CREATE TABLE ADDRESSCHANGES(

    EMPNO INT ,

    COLCHANGEDBITMASK INT, --example: saved so you can audit which cols actually changed, but they are both here anyway!

    OLDENAME VARCHAR(100),

    OLDADDR1 VARCHAR(100),

    OLDADDR2 VARCHAR(100),

    OLDCITY VARCHAR(100),

    OLDSTATECODE VARCHAR(2),

    OLDZIPCODE VARCHAR(100),

    OLDPHONE VARCHAR(20),

    NEWENAME VARCHAR(100),

    NEWADDR1 VARCHAR(100),

    NEWADDR2 VARCHAR(100),

    NEWCITY VARCHAR(100),

    NEWSTATECODE VARCHAR(2),

    NEWZIPCODE VARCHAR(100),

    NEWPHONE VARCHAR(20))

    GO

    --modified from http://www.sqlservercentral.com/Forums/Topic593727-148-1.aspx#bm595054

    CREATE TRIGGER TR_MYADDRESSES

    ON MYADDRESSES

    AFTER UPDATE AS

    /*Check whether columns 2 thru 8 have been updated. If any or all

    columns 2, 3 or 4 have been changed, create an audit record. The

    bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14. To test

    whether all columns 2, 3, and 4 are updated, use = 14 instead of > 0

    (below).

    this one specifically is for 3 thru 8 is:

    select power(2,(3-1))

    + power(2,(4-1))

    + power(2,(5-1))

    + power(2,(6-1))

    + power(2,(7-1))

    + power(2,(8-1)) = 252*/

    --IF (COLUMNS_UPDATED()) <> 0

    IF (substring(COLUMNS_UPDATED(),1,1) & 252 )>0

    BEGIN

    --inside a trigger, two special tables exist for the duration of the trigger:

    --the table INSERTED and the table DELETED

    --an UPDATE would have data in both tables...the value WAS DELETED to be replaced with the value from INSERTED

    INSERT INTO ADDRESSCHANGES(EMPNO, COLCHANGEDBITMASK, OLDENAME, OLDADDR1, OLDADDR2, OLDCITY, OLDSTATECODE, OLDZIPCODE, OLDPHONE, NEWENAME, NEWADDR1, NEWADDR2, NEWCITY, NEWSTATECODE, NEWZIPCODE, NEWPHONE)

    SELECT

    DELETED.EMPNO,

    COLUMNS_UPDATED(),

    DELETED.ENAME,

    DELETED.ADDR1,

    DELETED.ADDR2,

    DELETED.CITY,

    DELETED.STATECODE,

    DELETED.ZIPCODE,

    DELETED.PHONE,

    INSERTED.ENAME,

    INSERTED.ADDR1,

    INSERTED.ADDR2,

    INSERTED.CITY,

    INSERTED.STATECODE,

    INSERTED.ZIPCODE,

    INSERTED.PHONE

    FROM DELETED

    INNER JOIN INSERTED

    ON DELETED.EMPNO = DELETED.EMPNO

    END;

    GO

    --insert some test data

    INSERT INTO MYADDRESSES( ENAME, ADDR1, ADDR2, CITY, STATECODE, ZIPCODE, PHONE, MOREDATA)

    SELECT 'Kalvin','123 My Imagination St','','Miami','FL','33024','555-1212','likes snowmen'

    UNION

    SELECT 'Hobbes','123 My Imagination St','','Miami','FL','33024','555-1222','likes to tease calvin'

    --renaming Calvin doesn't raise the trigger

    UPDATE MYADDRESSES SET ENAME='Calvin' where ENAME='Kalvin'

    --changing the Address DOES:

    UPDATE MYADDRESSES SET ADDR1='123 G.R.O.S.S. Clubhouse' where ENAME='Calvin'

    --changing multiple rows at the same time does trigger

    UPDATE MYADDRESSES SET STATECODE='NY'

    --setting the value to the same value repeating a previous insert:

    UPDATE MYADDRESSES SET ADDR1='123 G.R.O.S.S. Clubhouse' where ENAME='Calvin'

    select * from MYADDRESSES

    select * from ADDRESSCHANGES

    drop trigger TR_MYADDRESSES

    drop table MYADDRESSES

    drop table ADDRESSCHANGES

    Lowell


    --help us help you! If you post a question, make sure you include a CREATE TABLE... statement and INSERT INTO... statement into that table to give the volunteers here representative data. with your description of the problem, we can provide a tested, verifiable solution to your question! asking the question the right way gets you a tested answer the fastest way possible!