0

In PostgreSQL we can have triggers like this:

CREATE TRIGGER tr_info_changed
BEFORE INSERT OR UPDATE
ON t_info
FOR EACH ROW
EXECUTE PROCEDURE tf_table_changed();

With tf_table_changed() beeing a Trigger Function like this:

CREATE OR REPLACE FUNCTION tf_table_changed()
  RETURNS trigger AS
$BODY$
    BEGIN
        IF (TG_OP = 'INSERT') THEN
        -- Keep track of record insertion.
            NEW.created = current_timestamp;
            NEW.changed = NEW.created; -- Times of change and insertion are identical.
            RETURN NEW;
        END IF;
        IF (TG_OP = 'UPDATE') THEN
        -- Keep track of changes.
            NEW.created = OLD.created; -- EF would overwrite value.
            NEW.changed = current_timestamp;
            RETURN NEW;
        END IF;
        RETURN NULL;
    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

In Transact-SQL I have this so far:

CREATE TRIGGER [dbo].[Trigger_Setting_Created]
  ON [dbo].[T_Setting] AFTER INSERT
AS
  UPDATE s SET Created = GETDATE(), Changed = GETDATE()
  FROM T_Setting AS s
  INNER JOIN inserted AS i
    ON s.SessionToken = i.SessionToken
GO

I ommit the second trigger for the update case.

As we can see when we want to keep all Created/Updated up to date in each and every of our tables it is getting very cumbersome in Transact-SQL with lots of copy&paste and modifying each trigger hopefully not forgetting any table-specific changes whereas in PostgreSQL things are DRY and simple.

Question: Is there an equivalent in Transact-SQL with respect for DRYness?

markus s
  • 1,024
  • 1
  • 11
  • 20
  • You are asking for the *opposite* of DRY - you are repeating the same modification inside a slow cursor. That's not the SQL (language, set-oriented) way. You already have the new values in `inserted` and the old values in `deleted`. What else do you want? BTW should you be using an INSTEAD OF trigger? – Panagiotis Kanavos Dec 20 '17 at 09:08
  • Can you just add a default value to the created and changed date of GETDATE() and just have a FOR UPDATE TRIGGER to update the changed date to GETDATE() – Steve Ford Dec 20 '17 at 09:14
  • @Steve Ford I will have a look at this. – markus s Dec 20 '17 at 09:21
  • @PanagiotisKanavos I cannot see why the PostgresSQL is the opposite of DRY? I Create tf_table_changed() once and will never ever have to repeat it again. I don't need the values which have been changed but rather want to update the created/changed dates on inserts and updates so that you can ommit and thus are not able to wrong them whenever you commit queries. – markus s Dec 20 '17 at 09:29
  • Because instead of using a set-based operation *once* you use a cursor to perform multiple operations in the slowest way possible. Join the tables and perform the operations you want. BTW, if you target SQL Server 2016 you don't need the triggers at all since SQL Server introduced system-versioned temporal tables. – Panagiotis Kanavos Dec 20 '17 at 09:41
  • If you don't really need temporal tables, then a) just add a default value for `Created`, `Changed`, no need for trigger and b) use only an `AFTER UPDATE ` trigger to set `Changed` – Panagiotis Kanavos Dec 20 '17 at 09:42
  • Finally, regarding the comment `EF would overwrite value.` it won't if you tell it it's a computed property with `[DatabaseGenerated(DatabaseGeneratedOption.Computed)]`, as shown [here](https://stackoverflow.com/questions/6564772/ef-code-first-readonly-column). Without this mapping, it would be impossible to work with computed columns – Panagiotis Kanavos Dec 20 '17 at 09:45

0 Answers0