SQL - 友谊表的最佳实践

Mar*_*rko 11 sql t-sql sql-server database-design data-modeling

在你向我展示重复之前,请注意我在网站上搜索了一些已找到的例子,但对我的问题并不十分具体:)

在SQL中创建友谊表的最佳方法是什么,但确保每一行都是唯一的,即不管属于哪个列,相同的UserID和FriendID永远不会被赋予?

我有这个粗略的例子

CREATE TABLE [dbo].[Friendship](
    [UserID] [uniqueidentifier] NOT NULL,
    [FriendID] [uniqueidentifier] NOT NULL,
    [FriendshipStatus] [int] NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

User表和FriendID共有2个Users表的外键.

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

UserID    FriendID    FriendshipStatus
Guid 123   Guid 789    1
Guid 789   Guid 123    1
Run Code Online (Sandbox Code Playgroud)

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

OMG*_*ies 15

使FRIENDSHIP表的主键为:

  • 用户身份
  • friendid

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

停止反向对

为了停止反向对 - userid"789"和friendid"123" - 您需要包含逻辑以检查存储过程,函数或触发器中的表是否已存在.如果反向不存在,则userid <friendid的CHECK约束将停止有效尝试添加用户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)
Run Code Online (Sandbox Code Playgroud)


ara*_*nid 6

Quassnoi 写了一篇文章解释为什么你可能想要一个每对两行的表格版本,以使查询更容易:http : //explainextended.com/2009/03/07/selecting-friends/

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