我有一个SQL Server 2016表,其中在任何给定时间都应只有一条记录处于活动状态。会有CRUD操作。
我正在尝试在该表上创建唯一的非聚集索引,以使其在任何时候都只有1条活动记录。有效记录的标准是今天的日期是否在StartDate
和StopDate
之间。 ID是唯一键。对于其他情况,我不确定我的语法和策略是否正确。
这是我的SQL:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[GWFO_FlashNewsItem]
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[Title] [VARCHAR](150) NOT NULL,
[NavigateToURL] [VARCHAR](250) NULL,
[StartDate] [SMALLDATETIME] NOT NULL,
[StopDate] [SMALLDATETIME] NULL,
[Active] [BIT] NOT Null,
[UpdateSOEID] [CHAR](7) NULL,
[UpdateDate] [SMALLDATETIME] NULL,
CONSTRAINT [PK_GWFO_FlashNewsItem]
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]
CREATE UNIQUE NONCLUSTERED INDEX uixf_GWFO_FlashNews_Active_filtered
ON GWFO_FlashNewsItem (Active)
INCLUDE (ID, Title)
WHERE Active = 1
答案 0 :(得分:0)
从上下文来看,似乎您正试图限制插入或更新的记录的日期范围不在当前日期。为此,您可以使用触发器。如果日期范围不符合您的活动标准,则可能会引发错误并阻止插入或更新。
我还尝试创建一个检查约束,并且效果很好:
CREATE TABLE [dbo].[test]
(
[d1] [DATETIME] NULL,
[d2] [DATETIME] NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[test] WITH CHECK
ADD CONSTRAINT [CK_test] CHECK ((GETDATE() >= [d1] AND GETDATE() <= [d2]))
GO
ALTER TABLE [dbo].[test] CHECK CONSTRAINT [CK_test]
GO
此代码:
INSERT INTO test SELECT '1/1/2000', '1/1/2001'
引发此错误:
信息547,级别16,状态0,第24行
INSERT语句与CHECK约束“ CK_test”冲突。数据库“ SysproSupport”的表“ dbo.test”中发生了冲突。该声明已终止。
尽管看来,最终您应该应该能够控制要在前端处理的记录类型。如果您有一个正在处理数据的应用程序或数据输入界面,则可以将这些约束放入其中。将其实现为约束或触发器将确保甚至管理员也无法在不禁用数据的情况下清除数据。
答案 1 :(得分:0)
我认为您首先需要更清楚地确定需要什么。例如,您有一个设置了活动位的记录,StartDate是今天0:00:00,StopDate是今天23:59:59,一切都很好。
直到23:59:59,您的条件(仅当GetDate()在StartDate和StopDate之间时才应设置有效位)不再有效。您认为那一刻会发生什么?那个位本身就神奇地转换为0?
另一个问题,即使满足条件,您的要求是否也应允许记录将Active设置为0?如果此问题的答案为“否”,则您的有效位不是单独的字段,而只是StartDate和StopDate的[不确定性]函数,您唯一需要注意的是不允许重叠的间隔。