这可能是一个比实体框架更广泛的SQL主题,我在这两个领域都是一个新手,但我会从实体框架的角度来问它。
我想强制执行多到八的关系。我的设置是:
我尝试了以下内容:
1)在Person和PersonGroup之间添加8个1..many关联。使用此解决方案,每组不能超过8个人。但是,为了找到一个人所在的所有组,我需要在Person字段中迭代8个变量,这很笨重。
2)向PersonGroup添加8个与人匹配的ID。再一次,我可以保证每组只有8个人,但没有自动链接通过Person-&gt的关联; PersonGroup。我现在需要确保将它添加到两个地方。
3)只需做很多很多关系并在代码中处理它。这有两个问题:我不能保证每组只有8个人,我不确定我是否可以保证订单保持不变。
那么,哪个是最好的,或者我错过了什么解决方案?
答案 0 :(得分:3)
多对多对我来说似乎没问题。通过实施触发器,您可以轻松确保每组不超过8人。此外,如果您认为它对您的逻辑很重要,您可以在此表中添加订单列。
答案 1 :(得分:3)
与“catch”的n:m
关系:
Person
------
PersonId
PRIMARY KEY (PersonId)
PersonGroup
-----------
GroupId
PRIMARY KEY (GroupId)
Belongs
-------
GroupId
PersonId
Ordering
PRIMARY KEY (GroupId, PersonId)
FOREIGN KEY (GroupId)
REFERENCES PersonGroup (GroupId)
FOREIGN KEY (PersonId)
REFERENCES Person (PersonId) --- all normal up to here
UNIQUE KEY (GroupId, Ordering) --- the "catch"
CONSTRAINT Ordering_chk --- ensuring only up to 8 persons
CHECK Ordering IN (1,2,3,4,5,6,7,8) --- per group
你应该确保你将使用的SQL引擎中有CHECK
约束(例如,MySQL会诱使你相信它有这样的约束,但它只是忽略它们.SQL-Server不会返回如果您尝试插入一个错误,但很高兴在已选中的列中添加NULL
。)
这种方法存在局限性。 Ordering
字段必须为NOT NULL
,因为如果它是NULL
,则可以插入超过8行(其中为NULL)(SQL-Server除外,这样只允许最多9行,8个带值,1个带NULL。)
要确保Ordering
中最多8行和NULL,您可以制作更复杂的约束,如MSDN site, CHECK Constraints中描述的约束(如果您的RDBMS具有此类功能),但我不在对这样一个野兽的表现一定肯定:
CREATE FUNCTION CheckMax8PersonPerGroup()
RETURNS int
AS
BEGIN
DECLARE @retval int
SELECT @retval = CASE WHEN EXISTS
( SELECT *
FROM Belongs
GROUP BY GroupId
HAVING COUNT(*) > 8
)
THEN 0
ELSE 1
END
RETURN @retval
END;
GO
ALTER TABLE Belongs
ADD CONSTRAINT Ordering_chk
CHECK (CheckMax8PersonPerGroup() = 1 );
GO
也可以将约束创建为FOREIGN KEY
到具有8行的引用表。 (如果你使用MySQL,这是相当于CHECK
的唯一方法。)
变体是使用(GroupId, Ordering)
作为主键,而不对(GroupId, PersonId)
组合有任何约束。这将允许Person
在Group
中有多个位置(但仍然最多为8)。