Constraint for only one record marked as default

From a normalization perspective, this would be an inefficient way of storing a single fact.

I would opt to hold this information at a higher level, by storing (in a different table) a foreign key to the identifier of the row which is considered to be the default.

CREATE TABLE [dbo].[Foo](
    [Id] [int] NOT NULL,
 CONSTRAINT [PK_Foo] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[DefaultSettings](
    [DefaultFoo] [int] NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[DefaultSettings]  WITH CHECK ADD  CONSTRAINT [FK_DefaultSettings_Foo] FOREIGN KEY([DefaultFoo])
REFERENCES [dbo].[Foo] ([Id])
GO

ALTER TABLE [dbo].[DefaultSettings] CHECK CONSTRAINT [FK_DefaultSettings_Foo]
GO

Use a unique filtered index

On SQL Server 2008 or higher you can simply use a unique filtered index

CREATE UNIQUE INDEX IX_TableName_FormID_isDefault
    ON TableName(FormID)
    WHERE isDefault = 1

Where the table is

CREATE TABLE TableName(
    FormID INT NOT NULL,
    isDefault BIT NOT NULL
)

For example if you try to insert many rows with the same FormID and isDefault set to 1 you will have this error:

Cannot insert duplicate key row in object 'dbo.TableName' with unique index 'IX_TableName_FormID_isDefault'. The duplicate key value is (1).

Source: http://technet.microsoft.com/en-us/library/cc280372.aspx


Here's a modification of Damien_The_Unbeliever's solution that allows one default per FormID.

CREATE VIEW form_defaults
AS
SELECT FormID
FROM whatever
WHERE isDefault = 1
GO
CREATE UNIQUE CLUSTERED INDEX ix_form_defaults on form_defaults (FormID)
GO

But the serious relational folks will tell you this information should just be in another table.

CREATE TABLE form
FormID int NOT NULL PRIMARY KEY
DefaultWhateverID int FOREIGN KEY REFERENCES Whatever(ID)

Tags:

Sql

Sql Server