我希望确保我的数据具有以下检查(约束?)的约束
ArticleId INT PRIMARY KEY NOT NULL IDENTITY
HubId TINYINT NOT NULL
CategoryId INT NOT NULL
Title NVARCHAR(100) NOT NULL
Content NVARCHAR(MAX) NOT NULL
BorderColour VARCHAR(7) -- Can be nullable.
我在猜我是否必须制定检查限制?但我不确定如何等等。
样本数据。
1, 1, 1, 'test', 'blah...', '#FFAACC'
1, 1, 1, 'test2', 'sfsd', NULL
1, 1, 2, 'Test3', 'sdfsd dsf s', NULL
1, 1, 2, 'Test4', 'sfsdsss', '#AABBCC'
现在..如果我添加以下行,我应该得到一些SQL错误....
INSERT INTO tblArticle VALUES (1, 2, 'aaa', 'bbb', '#ABABAB')
任何想法?
答案 0 :(得分:3)
CHECK
约束通常应用于单行,但是,您可以使用UDF作弊:
CREATE FUNCTION dbo.CheckSingleBorderColorPerHubCategory
(
@HubID tinyint,
@CategoryID int
)
RETURNS BIT
AS BEGIN
RETURN CASE
WHEN EXISTS
(
SELECT HubID, CategoryID, COUNT(*) AS BorderColorCount
FROM Articles
WHERE HubID = @HubID
AND CategoryID = @CategoryID
AND BorderColor IS NOT NULL
GROUP BY HubID, CategoryID
HAVING COUNT(*) > 1
) THEN 1
ELSE 0
END
END
然后创建约束并引用UDF:
ALTER TABLE Articles
ADD CONSTRAINT CK_Articles_SingleBorderColorPerHubCategory
CHECK (dbo.CheckSingleBorderColorPerHubCategory(HubID, CategoryID) = 1)
答案 1 :(得分:2)
如果您运行SQL2008,则可以使用另一个可用选项。此版本的SQL具有称为筛选索引的功能。
使用此功能,您可以创建一个唯一索引,其中包括除BorderColour为null之外的所有行。
CREATE TABLE [dbo].[UniqueExceptNulls](
[HubId] [tinyint] NOT NULL,
[CategoryId] [int] NOT NULL,
[BorderColour] [varchar](7) NULL,
)
GO
CREATE UNIQUE NONCLUSTERED INDEX UI_UniqueExceptNulls
ON [UniqueExceptNulls] (HubID,CategoryID)
WHERE BorderColour IS NOT NULL
这种方法比我在其他答案中的方法更清晰,因为它不需要创建额外的计算列。它也不要求你在表中有一个唯一的列,尽管你应该拥有它。
最后,它也将比UDF / Check Constraint解决方案快得多。
答案 2 :(得分:0)
你也可以用这样的东西做一个触发器(这实际上是矫枉过正的 - 你可以通过假设数据库已经处于有效状态 - 即UNION而不是UNION等来使它更清晰):
IF EXISTS (
SELECT COUNT(BorderColour)
FROM (
SELECT INSERTED.HubId, INSERTED.CategoryId, INSERTED.BorderColour
UNION ALL
SELECT HubId, CategoryId, BorderColour
FROM tblArticle
WHERE EXISTS (
SELECT *
FROM INSERTED
WHERE tblArticle.HubId = INSERTED.HubId
AND tblArticle.CategoryId = INSERTED.CategoryId
)
) AS X
GROUP BY HubId, CategoryId
HAVING COUNT(BorderColour) > 1
)
RAISEERROR
答案 3 :(得分:0)
如果表中有唯一列,则可以通过在计算机列上创建唯一约束来完成此操作。
以下示例创建了一个表,其行为与您在需求中描述的一样,并且应该比基于UDF的检查约束执行得更好。您还可以通过使计算列保持不变来进一步提高性能。
CREATE TABLE [dbo].[UQTest](
[Id] INT IDENTITY(1,1) NOT NULL,
[HubId] TINYINT NOT NULL,
[CategoryId] INT NOT NULL,
[BorderColour] varchar(7) NULL,
[BorderColourUNQ] AS (CASE WHEN [BorderColour] IS NULL
THEN cast([ID] as varchar(50))
ELSE cast([HuBID] as varchar(3)) + '_' +
cast([CategoryID] as varchar(20)) END
),
CONSTRAINT [UQTest_Unique]
UNIQUE ([BorderColourUNQ])
)
上述实现的一个可能不合需要的方面是它允许类别/集线器同时定义Null和颜色。如果这是一个问题,请告诉我,我会调整我的答案来解决这个问题。
PS:对我以前的(不正确的)答案感到抱歉。我没有仔细阅读这个问题。