唯一的列对为A,B或B,A

时间:2009-05-10 03:47:10

标签: sql mysql

如果我有一个包含两列,TeamA和TeamB的连接表,我如何确保每一对都是唯一的?

显然我可以在这些列上放置一个唯一的复合索引,但这样只能确保A,B顺序的唯一性,而不是B,A是否正确?

TeamA | TeamB
-------------
 red  | blue
 pink | blue
 blue | red

如您所见,Red vs. Blue已被指定为第一个记录,然后再次指定为最后一个记录。这应该是非法的,因为他们已经面对面了。

编辑:此外,还有办法处理SELECT案例吗?还是UPDATE?删除?等。

此外,家庭或客队的想法已经提出,这在这里可能很重要。在考虑如何在数据库端构建包围系统时,我想到了这个初始概念。

4 个答案:

答案 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 
    )