以「抓」的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
你應該確保在CHECK
約束是在你使用SQL引擎可用的(MySQL的例子就是誘騙用戶相信它有這樣但它只是忽略它們SQL-Server不會返回錯誤,但如果您嘗試插入一個,則在檢查列中愉快地添加NULL
)。
這種方法存在限制。 Ordering
字段必須是NOT NULL
,因爲如果它是NULL
,可以插入超過8行(其中包含NULL)(SQL-Server除外,只允許最多9行,其中8個包含值,另一個包含NULL)。)
爲了確保最高的8行和NULL值在Ordering
的,你可以讓像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)中具有多個職位。