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.
Use an unique filtered index:
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.