【发布时间】:2020-06-08 10:16:15
【问题描述】:
我有一个带有列的表格:
Id int
Name varchar *
Description varchar
LevelId int *
DeletedAt datetime nullable *
我想对上面标有星号的字段设置唯一约束:Name、LevelId、DeletedAt。我为约束添加 DeletedAt 的原因是,当有人软删除并添加具有相同名称和 LevelId 的新记录时,数据库将允许添加。但是我错误地认为不允许有 2 行具有相同的 Name、LevelId 和 DeletedAt 的 NULL,因为 NULL 不等于 NULL。
我需要的是一个替代方案。我怎样才能支持这个要求?我能想到的一件事是用 varchar 替换 DeletedAt,然后它有一个默认值,例如“Active”或一个空字符串(只是不为空),然后将日期作为已删除行的字符串。但我在想是否有更优雅的解决方案。
【问题讨论】:
-
在 SQL Server 中,唯一约束中只允许有一个
NULL,完全符合您的要求。 -
参见例如this question 这只是人们寻求您(并非不合理地)假设已经是这种情况的众多行为之一。
-
我使用的是 SQL Server 2014,在上面的架构中,我可以在 DeletedAt 上输入 2 条具有相同名称、LevelId 和 NULL 的记录。我需要的是不允许这样做。我最初认为这是不允许的,因为我认为 NULL 将等于 NULL,但它并不限制我为 2 条记录输入相同的值。我需要一些东西来替换可为空的 DeletedAt 列。
-
我根据您上面的描述在 SQL Server 2014 中创建了一个表,并尝试输入两行匹配的名称、描述和 DeletedAt。错误信息是
Msg 2601, Level 14, State 1, Line 1 Cannot insert duplicate key row in object 'dbo.T' with unique index 'IX_T'. The duplicate key value is (abc, def, <NULL>). -
事实上,这甚至在 documentation 中都有说明 - "... UNIQUE 约束允许值 NULL。但是,与参与 UNIQUE 的任何值一样约束,每列只允许一个空值"
标签: sql-server database-design