views:

14

answers:

1

Using SQL Server 2008, I have a requirement that email addresses in my user table must be unique, but email addresses are not required in my app. I've tried to make email addresses required, but I just cannot get the customer to budge on this one. What is the best method to create this constraint? If I add a constraint, what does the constraint look like? If I add a before insert trigger, what does that look like?

This application will be running on a multi-server web farm, and there are multiple points of entry. An application-level lock() { } is not a great option. I'm doing a select and verifying that the email doesn't exist from code right before performing the insert operation to give immediate feedback to the user. However, I would really like a database-level solution here. Just in case.

I'm using an ORM (NHibernate with AutoMapping), so I'd rather not insert or update records with a stored procedure.

+1  A: 

Use an unique filtered index:

create table Foo (
 Id int not null identity(1,1) primary key
 , Name varchar(256) null
 , Address varchar(max) null
 , Email varchar(256) null);

create index ndxFooEmail unique on Foo(Email) 
 where Email is not null;

This is a sure-shot 100% bullet proof way to guarantee uniqueness of an optional value. The uniqueness will be enforced in the database server, your ORM/DAL does not need to worry with it, simply handle the error if the unique constraint is violated rather than try to duplicate the constraint in the ORM/DAL (is not really possible to do it correctly under concurrency).

See Filtered Index Design Guidelines for more details about SQL Server 2008 filtered indexes.

Remus Rusanu
Boom! Headshot!
Jarrett Meyer

related questions