SQL - 友谊表的最佳实践

时间:2010-11-18 21:55:01

标签: sql sql-server tsql database-design data-modeling

  

在您向我显示重复项之前,请注意我在网站上搜索了一些一些示例,但对我的问题并不十分具体:)

在SQL中创建友谊表的最佳方法是什么,但要确保每一行都是唯一的,因为无论相同的UserID和FriendID属于哪一列,都不会被允许?

我有这个粗略的例子

CREATE TABLE [dbo].[Friendship](
    [UserID] [uniqueidentifier] NOT NULL,
    [FriendID] [uniqueidentifier] NOT NULL,
    [FriendshipStatus] [int] NOT NULL
)

User表有2个外键,来自UserID和FriendID。

目前,我可以在用户两次之间插入友谊,从而创建副本。实施例

UserID    FriendID    FriendshipStatus
Guid 123   Guid 789    1
Guid 789   Guid 123    1

如何确保强制执行此完整性,可能 2 PK ?某种独特的指数?或者你会建议一起更好的桌子设计吗?另外,你会自动增量FriendshipID吗?如果是这样,你能解释一下原因吗?

5 个答案:

答案 0 :(得分:15)

使FRIENDSHIP表的主键为:

  • 用户ID
  • friendid

...将确保您不能按顺序重复。这意味着,它将阻止您添加用户ID“123”和friendid“789”的重复项。如果包含状态列,则不再是这种情况,因为不同的状态值将允许重复用户ID和friendid列。

停止反向对

为了停止反向对 - userid“789”和friendid“123” - 您需要包含逻辑以检查存储过程,函数或触发器中的表中是否已存在该对。用户ID的CHECK约束<如果反向不存在,friendid将停止有效尝试添加用户ID“789”和friendid“123”。

INSERT INTO FRIENDSHIP
SELECT @userid, @friendid, 1
  FROM FRIENDSHIP f
 WHERE NOT EXISTS(SELECT NULL
                    FROM FRIENDSHIP t
                   WHERE (t.userid = @friendid AND t.friendid = @userid)
                      OR (t.userid = @userid AND t.friendid = @friendid)

答案 1 :(得分:4)

Quassnoi撰写了一篇文章,解释了为什么您可能希望拥有每对两行的表格版本,以便于查询:http://explainextended.com/2009/03/07/selecting-friends/

(文章讨论了MySQL,但值得记住,作为任何SQL数据库的性能技术)

答案 2 :(得分:1)

我做了一个小小的更改来执行内部查询,并在最后完成括号时只返回存在的记录(双表)

INSERT INTO FRIENDSHIP
SELECT @userid, @friendid, 1
  FROM DUAL f
 WHERE NOT EXISTS(SELECT NULL
                FROM FRIENDSHIP t
               WHERE (t.userid = @friendid AND t.friendid = @userid)
                  OR (t.userid = @userid AND t.friendid = @friendid) )

答案 3 :(得分:0)

Table User: UserId
Table Friendship: FriendshipId
Table UserFriendships: UserId, FriendshipId, FriendshipStatus

您可以添加UNIQUE约束以防止用户两次加入友谊。


您拥有用户和友谊。用户可以通过在第三个表中创建记录来加入友谊(可以是0个或更多用户)。

答案 4 :(得分:0)

用户(用户ID) 友谊(User1ID,User2ID,FriendshipStatus)

检查约束:User1ID< User2ID

唯一约束:User1ID,User2ID