SQL 唯一约束允许违反空值
SQL Unique Constraint allows violation with nulls
我有一个 table,它在 3 列上有一个非聚集的唯一索引,"MenuId"、"Name" 和 "ParentId"。
问题是,当 ParentId 设置为 NULL 时,我可以向此 table 中插入多行,如下所示。
如果我尝试添加重复行并且 ParentId 不为空,则唯一约束会按预期工作。
我对唯一索引的理解是,它只允许参与索引的列的单个唯一组合,所以我希望下图中能够插入第一行,但它应该抛出插入第二(和第三)行时违反索引的异常 - 但它没有。
我哪里错了?
我正在使用 SQL LocalDb。
更新:我正在使用 EF Core 从代码生成数据库,似乎在这种情况下,正在使用 WHERE 子句创建唯一约束以在 ParentId 或 Name 为 NULL 时忽略:
CREATE UNIQUE NONCLUSTERED INDEX [IX_MenuItem_MenuId_ParentId_Name]
ON [dbo].[MenuItem]([MenuId] ASC, [ParentId] ASC, [Name] ASC)
WHERE ([ParentId] IS NOT NULL AND [Name] IS NOT NULL);
令人尴尬的是,当我在 SQL 服务器资源管理器属性 window 中探索唯一约束时,这个 WHERE 子句并不明显 - 我只是检查了唯一约束存在,并且我的列expected where included - 但这还不够。感谢下面的评论员,他无法重现并让我实际检查脚本以查找此 WHERE 子句变得明显的索引。我现在已将我的问题转移到一个与 EF 为什么在我的案例中产生这个问题有关的问题:
https://github.com/aspnet/EntityFrameworkCore/issues/17586
将-1设置为默认值ParentId
。
或者
ALTER TABLE TableName
ADD CONSTRAINT cUniq UNIQUE (MenuId,Name,ParentId);
感谢@萧为元提示我更详细地查看 Unique 约束,而不仅仅是属性 window!
UNIQUE 索引有一个 WHERE 子句,导致它忽略父 ID 或名称具有 NULL 值的记录:
CREATE UNIQUE NONCLUSTERED INDEX [IX_MenuItem_MenuId_ParentId_Name]
ON [dbo].[MenuItem]([MenuId] ASC, [ParentId] ASC, [Name] ASC)
WHERE ([ParentId] IS NOT NULL AND [Name] IS NOT NULL);
这是由 EF 生成的 - 这就是你在依赖 ORM 为你做事并假设他们做你想做的事情时遇到的问题 - 拍打自己的手腕
我有一个 table,它在 3 列上有一个非聚集的唯一索引,"MenuId"、"Name" 和 "ParentId"。
问题是,当 ParentId 设置为 NULL 时,我可以向此 table 中插入多行,如下所示。
如果我尝试添加重复行并且 ParentId 不为空,则唯一约束会按预期工作。
我对唯一索引的理解是,它只允许参与索引的列的单个唯一组合,所以我希望下图中能够插入第一行,但它应该抛出插入第二(和第三)行时违反索引的异常 - 但它没有。
我哪里错了?
我正在使用 SQL LocalDb。
更新:我正在使用 EF Core 从代码生成数据库,似乎在这种情况下,正在使用 WHERE 子句创建唯一约束以在 ParentId 或 Name 为 NULL 时忽略:
CREATE UNIQUE NONCLUSTERED INDEX [IX_MenuItem_MenuId_ParentId_Name]
ON [dbo].[MenuItem]([MenuId] ASC, [ParentId] ASC, [Name] ASC)
WHERE ([ParentId] IS NOT NULL AND [Name] IS NOT NULL);
令人尴尬的是,当我在 SQL 服务器资源管理器属性 window 中探索唯一约束时,这个 WHERE 子句并不明显 - 我只是检查了唯一约束存在,并且我的列expected where included - 但这还不够。感谢下面的评论员,他无法重现并让我实际检查脚本以查找此 WHERE 子句变得明显的索引。我现在已将我的问题转移到一个与 EF 为什么在我的案例中产生这个问题有关的问题: https://github.com/aspnet/EntityFrameworkCore/issues/17586
将-1设置为默认值ParentId
。
或者
ALTER TABLE TableName
ADD CONSTRAINT cUniq UNIQUE (MenuId,Name,ParentId);
感谢@萧为元提示我更详细地查看 Unique 约束,而不仅仅是属性 window!
UNIQUE 索引有一个 WHERE 子句,导致它忽略父 ID 或名称具有 NULL 值的记录:
CREATE UNIQUE NONCLUSTERED INDEX [IX_MenuItem_MenuId_ParentId_Name]
ON [dbo].[MenuItem]([MenuId] ASC, [ParentId] ASC, [Name] ASC)
WHERE ([ParentId] IS NOT NULL AND [Name] IS NOT NULL);
这是由 EF 生成的 - 这就是你在依赖 ORM 为你做事并假设他们做你想做的事情时遇到的问题 - 拍打自己的手腕