Contrainte unique basée sur les grands-parents dans SQL Server

J'ai la structure de table suivante:

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

Je veux une contrainte unique disant que deux enfants ne peuvent pas avoir le même ChildTypeId s'ils ont un GrandParentId commun. Est-ce possible avec SQL Server?

Vous ne pouvez pas le faire avec une contrainte UNIQUE, mais vous pouvez le faire avec une contrainte CHECK qui appelle un UDF.

Écrivez un UDF qui prend un ChildId et interroge un JOIN de Child et Parent pour voir s'il y a un autre enfant avec le même GrandParentID et ChildTypeId. S'il y en a, renvoyez vrai / faux.

Ensuite, dans la contrainte CHECK, appelez cette fonction, en passant le ChildId, et vérifiez si le résultat de la fonction est vrai / faux.

Vous pouvez aussi le faire avec un TRIGGER, mais je préfère les contraintes.

Pour accélérer les autres qui trébuchent sur ce post, voici un exemple SQL de ce que Tab Alleman suggère:

 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 

puis ajoutez la contrainte de vérification avec quelque chose comme

 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