仅标记为默认的一条记录的约束

Pro*_*ofK 35 sql sql-server

如何在表上设置约束,以便只有一个记录的isDefault位字段设置为1?

约束不是表范围,而是由FormID指定的每组行的一个默认值.

Yve*_* M. 51

使用唯一的筛选索引

在SQL Server 2008或更高版本上,您只需使用唯一的筛选索引即可

CREATE UNIQUE INDEX IX_TableName_FormID_isDefault
    ON TableName(FormID)
    WHERE isDefault = 1
Run Code Online (Sandbox Code Playgroud)

表是哪里的

CREATE TABLE TableName(
    FormID INT NOT NULL,
    isDefault BIT NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

例如,如果您尝试插入多个具有相同FormId且isDefault设置为1的行,则会出现此错误:

无法在对象'dbo.TableName'中插入具有唯一索引'IX_TableName_FormID_isDefault'的重复键行.重复键值为(1).

资料来源:http://technet.microsoft.com/en-us/library/cc280372.aspx

  • 过滤的索引需要ANSI PADDING ON.因此,在创建过滤索引之前执行`SET ANSI PADDING ON`. (2认同)

Tom*_*ure 9

这是Damien_The_Unbeliever解决方案的修改,允许每个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
Run Code Online (Sandbox Code Playgroud)

但是严肃的关系人会告诉你这些信息应该只在另一张表中.

CREATE TABLE form
FormID int NOT NULL PRIMARY KEY
DefaultWhateverID int FOREIGN KEY REFERENCES Whatever(ID)
Run Code Online (Sandbox Code Playgroud)

  • +1"严肃的关系人会做什么"回答..我从有一个布尔值分成一个单独的表 (8认同)

Ian*_*son 8

从标准化的角度来看,这将是存储单个事实的低效方式.

我会选择通过将(在不同的表中)外键存储到被认为是默认行的行的标识符(更高级别)来保存此信息.

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
Run Code Online (Sandbox Code Playgroud)

  • 是的,但是这个替代解决方案仍然允许通过在dbo.DefaultSettings中插入许多行来实现多个默认值.如果你选择了那个方法,可以在dbo.DefaultSettings中添加一个触发器,只允许在那里有1行. (4认同)