Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UNIQUE constraint controlled by a bit column

I have a table, something like

FieldsOnForms(
 FieldID int (FK_Fields)
 FormID int (FK_Forms)
 isDeleted bit
)

The pair (FieldID,FormID) should be unique, BUT only if the row is not deleted (isDeleted=0).

Is it possible to define such a constraint in SQLServer 2008? (without using triggers)

P.S. Setting (FieldID, FormID, isDeleted) to be unique adds the possibility to mark one row as deleted, but i would like to have the chance to set n rows (per FieldID,FormID) to isDeleted = 1, and to have only one with isDeleted = 0

like image 797
jaraics Avatar asked Oct 22 '10 14:10

jaraics


People also ask

Which constraint used for making unique a column value?

A UNIQUE constraint can be referenced by a FOREIGN KEY constraint. When a UNIQUE constraint is added to an existing column or columns in the table, by default, the Database Engine examines the existing data in the columns to make sure all values are unique.

Can unique constraint have multiple columns?

You can define a UNIQUE constraint at the column or the table level. Only at the table level, you can define a UNIQUE constraint across multiple columns. Once a UNIQUE constraint is defined, if you attempt to insert or update a value that already exists in the column, SQLite will issue an error and abort the operation.

Is unique a column constraint?

The UNIQUE constraint ensures that all values in a column are different. Both the UNIQUE and PRIMARY KEY constraints provide a guarantee for uniqueness for a column or set of columns.

How many columns can hold unique constraints?

You can create a UNIQUE constraint on one or more columns of a table.


2 Answers

You can have a unique index, using the SQL Server 2008 filtered indexes feature, or you can apply a UNIQUE index against a view (poor man's filtered index, works against earlier versions), but you cannot have a UNIQUE constraint such as you've described.

An example of the filtered index:

 CREATE UNIQUE NONCLUSTERED INDEX IX_FieldsOnForms_NonDeletedUnique ON FieldsOnForms (FieldID,FormID) WHERE isDeleted=0
like image 157
Damien_The_Unbeliever Avatar answered Sep 27 '22 20:09

Damien_The_Unbeliever


You could change your IsDeleted column to a DeletedDate and make it a DATETIME with the exact time when the row was logically deleted. Alternatively, you could add a DeletedDate column and then create an IsDeleted computed column against that so that you still have that column available if it's being used in code. You would then of course put a unique index over the DeletedDate (in addition to the FieldID and FormId) instead of the IsDeleted column. That would allow exactly one NULL column.

Albin posted a solution similar to this, but then deleted it. I'm not sure why, but if he re-posts it then his was here before mine. :)

like image 31
Tom H Avatar answered Sep 27 '22 22:09

Tom H