过滤的索引表达式不适用于Bit

时间:2015-10-01 15:27:25

标签: sql sql-server tsql ssms

我想对列IsDefaultLanguage的某个值有一个bool约束:

Id...ISO639_ISO3166...ApplicationId...IsDefaultLanguage
1....de-de............1...............1
2....fr-fr............1...............1

第二个数据行插入应该导致一个唯一的错误,因为对于一个应用程序,IsDefaultLanguage只允许为True(1)。 一个语言也应该仅适用于一个应用程序。

Filter索引在我这边不起作用(Sql Server 2014)

我错了什么?

表格

CREATE TABLE [dbo].[Languages](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ISO639_ISO3166] [char](5) NOT NULL,
    [ApplicationId] [int] NOT NULL,
    [IsDefaultLanguage] [bit] NOT NULL,
 CONSTRAINT [PK_dbo.Languages] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[Languages]  WITH CHECK ADD  CONSTRAINT [FK_dbo.Languages_dbo.Applications_ApplicationId] FOREIGN KEY([ApplicationId])
REFERENCES [dbo].[Applications] ([Id])
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[Languages] CHECK CONSTRAINT [FK_dbo.Languages_dbo.Applications_ApplicationId]
GO

INDEX

CREATE UNIQUE NONCLUSTERED INDEX [IX_IsoCodeApplicationId] ON [dbo].[Languages]
(
    [ISO639_ISO3166] ASC,
    [ApplicationId] ASC,
    [IsDefaultLanguage] ASC
)
WHERE ([IsDefaultLanguage]=(1))
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

2 个答案:

答案 0 :(得分:1)

  

第二个数据行插入应该导致一个唯一的错误,因为对于一个应用程序,IsDefaultLanguage只允许为True(1)。一个语言也应该仅适用于一个应用程序。

以上对我来说不是很清楚。以下是我认为你想说的话:

  • IsDefaultLanguage1只能获得ApplicationId次值。
  • ISO639_ISO3166的值必须是每ApplicationId
  • 唯一的

如果是这种情况,请将您的索引拆分为2个单独的索引,以满足您的2个不同要求:

CREATE UNIQUE NONCLUSTERED INDEX [IX_IsoCodeApplicationId] ON [dbo].[Languages]
(
    [ISO639_ISO3166] ASC,
    [ApplicationId] ASC
)

CREATE UNIQUE NONCLUSTERED INDEX [IX_DefaultLanguageApplicationId] ON [dbo].[Languages]
(
    [IsDefaultLanguage] ASC,
    [ApplicationId] ASC,
)
WHERE ([IsDefaultLanguage]=(1))

答案 1 :(得分:0)

您的索引定义不正确,因为您尝试做的事情。让我们以另一种方式看待它。您希望以下查询返回0行:

select [ApplicationID], count(*)
from [dbo].[Languages]
where [IsDefaultLanguage] = 1
group by [ApplicationID]
having count(*) > 1

也就是说,根据ApplicationID,只有一行的值为IsDefaultLanguage = 1.因此,您的索引应为:

CREATE UNIQUE NONCLUSTERED INDEX [IX_IsoCodeApplicationId] 
ON [dbo].[Languages]
(
    [ApplicationId] ASC
)
WHERE ([IsDefaultLanguage]=(1))

完成与查询的类比,(read:can)只能在索引中每个ApplicationID占一行(因为它是唯一索引)。