基于SQL Server中的祖父母的唯一约束

时间:2016-05-11 13:51:26

标签: sql-server

我有以下表结构:

Grandparent - GrandParentId (PK)
Parent - ParentId (PK), GrandParentId (FK)
Child - ChildId (PK), ChildTypeId (FK), ParentId (FK)

我想要一个独特的约束,如果他们有一个共同的ChildTypeId,那么两个孩子就不能拥有相同的GrandParentId。这可能与SQL Server一起使用吗?

2 个答案:

答案 0 :(得分:1)

你不能用UNIQUE约束来做,但你可以用调用UDF的CHECK约束来做。

编写一个接收ChildId的UDF并查询Child和Parent的JOIN,以查看是否有另一个具有相同GrandParentID和ChildTypeId的子项。如果有,则返回true / false。

然后在CHECK约束中,调用该函数,传递ChildId,并检查函数的结果是否为true / false。

您也可以使用TRIGGER,但我更喜欢约束。

答案 1 :(得分:0)

加速其他人在这篇文章上磕磕绊绊,这是Tab Alleman建议的一个SQL示例:

CREATE FUNCTION Func_CousinsWithSameChildTypeId
(
    @childId uniqueidentifier,
    @parentId uniqueidentifier,
    @childTypeId uniqueidentifier
)
RETURNS bit
AS
BEGIN
    -- Declare the return variable here
    DECLARE @ResultVar bit

    SET @ResultVar = CASE 
        --assuming nullable - remove as necessary
        WHEN @parentId IS NOT NULL AND @childTypeId IS NOT NULL AND EXISTS(
            SELECT 1
            FROM dbo.Parents AS pAll
                INNER JOIN dbo.Children AS c ON c.ParentId = pAll.Id
            WHERE pAll.GrandParentId IN 
                (SELECT p1.GrandparentId
                 FROM dbo.Parents AS p1
                 WHERE p1.Id = @ParentId)
            AND c.Id <> @childId AND c.childTypeId = @childTypeId
        )
        THEN 1
        ELSE 0
    END

    -- Return the result of the function
    RETURN @ResultVar

END
GO

然后添加类似

的检查约束
ALTER TABLE [dbo].[Children] WITH CHECK ADD CONSTRAINT [CheckCousinsChildTypeId] CHECK  (([dbo].[Func_CousinsWithSameChildTypeId]([Id],[ParentId],[ChildTypeId])=(0)))
GO

ALTER TABLE [dbo].[Children] CHECK CONSTRAINT [CheckCousinsChildTypeId]
GO