Trying to add a trigger that inserts original data from 1 table to another. With getdate() appended to 2nd table.

  • I am trying to create a trigger on a table. Let's call it table ABC. Table looks like this:

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    CREATE TABLE [dbo].[ABC](

    [id] [uniqueidentifier] NOT NULL,

    [groupName] [nvarchar](max) NULL,

    [ruleCollectionJSON] [nvarchar](max) NULL,

    [isActive] [bit] NOT NULL,

    [ruleType] [int] NOT NULL

    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    GO

    When someone updates a row on table ABC, I want to insert the original values along with the current date and time getdate() into table ABCD with the current date and time into the updateDate field as defined below:

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    CREATE TABLE [dbo].[ABCD](

    [id] [uniqueidentifier] NOT NULL,

    [groupName] [nvarchar](max) NULL,

    [ruleCollectionJSON] [nvarchar](max) NULL,

    [isActive] [bit] NOT NULL,

    [ruleType] [int] NOT NULL,

    [updateDate] [date] NOT NULL

    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    GO

    The trigger I've currently written looks like this:

    /****** Object: Trigger [dbo].[ABC_trigger] Script Date: 4/10/2015 1:32:33 PM ******/

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    CREATE TRIGGER [dbo].[ABC_trigger] ON [dbo].[ABC]

    AFTER UPDATE

    AS

    IF UPDATE (ruleCollectionJSON)

    BEGIN

    INSERT INTO

    [dbo].[ActiveDirectoryGroupRulesArchive] (id, groupName, ruleCollectionJSON, isActive, ruleType, updateDate)

    select id, groupName, ruleCollectionJSON, isActive, ruleType, getdate()

    from [ActiveDirectoryGroupRules];

    END;

    GO

    SET ANSI_NULLS OFF

    GO

    SET QUOTED_IDENTIFIER OFF

    GO

    This trigger works, but it inserts all of the rows every time. My question is how can I get the trigger to just insert the last row updated?

    Any and all assistance would be greatly appreciated, what did I miss? Should be simple right? I can't sort by uniqueidentifier in descending as those can be random. Thanks in advance for the help anyone!!

  • you're not joining to the Inserted or Deleted virtual tables, so your result set is not getting filtered. Once you do that, only the affected records will be updated.

  • How would I do that?

  • Greg.Jackson (4/10/2015)


    How would I do that?

    You don't want to get the "last row" modified as you stated. You want to get ALL rows currently being modified. Remember that triggers in sql server are not called for each row, they are called for the entire operation.

    Here is one reference that you may find useful.

    https://msdn.microsoft.com/en-us/library/ms191300.aspx

    There are literally thousands of articles about this, just hit your old friend google and you will them. 😉

    _______________________________________________________________

    Need help? Help us help you.

    Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.

    Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.

    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
    Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
    Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/

  • Can anyone provide specific code?

  • Based on the tables above, in theory would this work:

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    ALTER TRIGGER [dbo].[ABC_trigger] ON [dbo].[ABC]

    AFTER UPDATE

    AS

    IF UPDATE (ruleCollectionJSON)

    BEGIN

    INSERT INTO

    [dbo].[ABCD] (id, groupName, ruleCollectionJSON, isActive, ruleType, updateDate)

    select TOP 1 id, groupName, ruleCollectionJSON, isActive, ruleType, getdate()

    from ABC TAB1, ABCD TAB2 where getdate() > (Select updateDate from TAB2);

    END;

  • For update you need to use deleted or inserted table.

    insert into abcd select *, getdate() from deleted if you want values before update.

  • Thank you!

    Just found that about 10 minutes ago. I didn't realize I could pull it from deleted.

    Thanks everyone. I was so close on my first attempt. I just wanted to pull it from deleted and not my original table.

  • As it has been noticed, on a trigger you should use inserted and deleted virtual tables.

    I'd use a different approach to be sure that the value on the column changed.

    CREATE TRIGGER [dbo].[ActiveDirectoryGroupRules_trigger] ON [dbo].[ActiveDirectoryGroupRules]

    AFTER UPDATE

    AS

    INSERT INTO [dbo].[ActiveDirectoryGroupRulesArchive]

    (

    id,

    groupName,

    ruleCollectionJSON,

    isActive,

    ruleType,

    updateDate

    )

    SELECT d.id,

    d.groupName,

    d.ruleCollectionJSON,

    d.isActive,

    d.ruleType,

    getdate()

    FROM Deleted d

    JOIN Inserted i ON i.id = d.id

    WHERE i.ruleCollectionJSON <> d.ruleCollectionJSON;

    GO

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • So the deleted virtual tables are similar to the oracle redo/undo.

    Correct?!

  • Not exactly. They're more like :old and :new

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2

Viewing 11 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic. Login to reply