如果我有一个包含两列,TeamA和TeamB的连接表,我如何确保每一对都是唯一的?
显然我可以在这些列上放置一个唯一的复合索引,但这样只能确保A,B顺序的唯一性,而不是B,A是否正确?
TeamA | TeamB
-------------
red | blue
pink | blue
blue | red
如您所见,Red vs. Blue已被指定为第一个记录,然后再次指定为最后一个记录。这应该是非法的,因为他们已经面对面了。
编辑:此外,还有办法处理SELECT案例吗?还是UPDATE?删除?等。
此外,家庭或客队的想法已经提出,这在这里可能很重要。在考虑如何在数据库端构建包围系统时,我想到了这个初始概念。
答案 0 :(得分:3)
定义一个约束,例如,A列中的值必须(按字母顺序或数字形)小于B列中的值:因此,您可以插入{blue,red}但不允许{红色,蓝色}因为蓝色小于红色。
答案 1 :(得分:2)
如果您的RDBMS(您未指定)支持触发器,则在该表上创建一个触发器以强制执行约束。
创建一个触发器,该触发器在INSERT上触发,该触发器检查对是否已经存在并且顺序颠倒了。如果它确实是ROLLBACK,否则允许插入。
答案 2 :(得分:1)
以下是一些与Mitch描述的触发器方法一起使用的示例代码。
我还没有测试过这段代码,而且这里已经很晚了: - )
CREATE TRIGGER trig_addTeam
ON Teams
FOR INSERT, UPDATE
AS
DECLARE @TeamA VARCHAR(100)
DECLARE @TeamB VARCHAR(100)
DECLARE @Count INT
SELECT @TeamA = (SELECT TeamA FROM Inserted)
SELECT @TeamB = (SELECT TeamB FROM Inserted)
SELECT @Count = (SELECT COUNT(*) FROM TEAMS WHERE (TeamA = @TeamA AND TeamB = @TeamB)
OR (TeamA = @TeamB AND TeamB = @TeamA))
IF @Count > 0 THEN
BEGIN
ROLLBACK TRANSACTION
END
这样做是为了查看当前表中是否存在A | B或B | A的序列。如果确实如此,则返回的计数大于零,并且事务将回滚而不会提交到数据库。
答案 3 :(得分:0)
如果存在相同的对(反向),请选择TeamA> TeamB。
SELECT DISTINCT TeamA, TeamB
FROM table t1
WHERE t1.TeamA > t1.TeamB
OR NOT EXISTS (
SELECT * FROM table t2
WHERE t2.TeamA = t1.TeamB AND t2.TeamB = t1.TeamA
)