Default Values, Triggers, and You

A friend of mine sent me an email the other day asking about default values in SQL Server. I realized that I’ve had to think about this a few times over the years and I’ve been asked about it more than once, too.

Setup

We need a table first, right? We’ll also want a few sample rows in there.``` CREATE TABLE Employees ( emp_id INT IDENTITY(1,1) NOT NULL PRIMARY KEY, emp_name varchar(50) NULL); GO

INSERT INTO Employees (emp_name) VALUES (‘a’); INSERT INTO Employees (emp_name) VALUES (‘b’); GO

SELECT * FROM Employees;

/* emp_id emp_name


1 a 2 b */


### How Defaults Work

So far we just have two rows in our two column table. It’s pretty boring. Let’s add a default value:```
ALTER TABLE Employees
ADD last_modified DATETIME NULL CONSTRAINT Employees_last_modified 
DEFAULT CURRENT_TIMESTAMP;
GO 
```We might as well add some new rows while we’re having fun with our employees, right?```
INSERT INTO Employees (emp_name) VALUES ('c');
INSERT INTO Employees (emp_name) VALUES ('d'); 
```What’s it look like now?```
SELECT * FROM Employees;

/*
emp_id      emp_name                                           last_modified
----------- -------------------------------------------------- -----------------------
1           a                                                  NULL
2           b                                                  NULL
3           c                                                  2010-12-06 18:21:37.787
4           d                                                  2010-12-06 18:21:37.787
*/ 
```Hold up. Employees 1 and 2 don’t have a `last_modified` value. Why not? Well, that’s because we’ve told SQL Server that our `last_modified` column can allow `NULL`s. They’re allowable in our table. If we wanted to automatically provide a default value when we added the constraint, we could do so by specifying the datatype as `DATETIME NOT NULL`. A best practice would be to add the column as a `NULL`able data type, add a value for all `NULL` rows, and set the column to `NOT NULL`. If we do want to update a `NULL`able column and set it to the default value, we just issue an update using the `DEFAULT` keyword for the value. If that makes no sense, perhaps this example will help:```
UPDATE Employees
SET last_modified = DEFAULT
WHERE last_modified IS NULL ; 

What About Updates?

UPDATE Employees
SET emp_name = 'zzz'
WHERE emp_id = 3;

SELECT * 
FROM Employees
WHERE emp_id = 3;

/*
emp_id      emp_name                                           last_modified
----------- -------------------------------------------------- -----------------------
3           zzz                                                2010-12-06 18:21:37.787
*/ 
```As you can see, when we update employee 3, it doesn’t change the value of`last_modified`. That’s because the default value is only set on insert. We could specify `DEFAULT` in our `UPDATE` statement, but then we’d need to specify that every time we update the table. What can we do?

### The Answer is Triggers

That’s right: triggers. If we want to track the modification timestamp of an object in the database, we need to use a trigger to keep things updated:```
CREATE TRIGGER TR_Employees$AfterUpdate ON dbo.Employees
AFTER UPDATE
AS
BEGIN
  UPDATE  e 
  SET     e.last_modified = CURRENT_TIMESTAMP
  FROM    dbo.Employees e 
          JOIN inserted i ON e.emp_id = i.emp_id;  
END
GO

UPDATE Employees 
SET emp_name = 'asdf'
WHERE emp_id = 1;

SELECT * FROM Employees;

/*
emp_id      emp_name                                           last_modified
----------- -------------------------------------------------- -----------------------
1           asdf                                               2010-12-06 18:34:04.340
2           b                                                  NULL
3           zzz                                                2010-12-06 18:21:37.787
4           d                                                  2010-12-06 18:21:37.787
*/ 
```And that, my friends, is how we keep a modification timestamp up to date.