SQL - Friendship 表的最佳实践

发布于 2024-10-03 05:39:31 字数 773 浏览 6 评论 0 原文

在向我展示重复项之前,请注意,我已经搜索过该网站并找到了一些示例,但并不完全针对我的问题:)

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

我有一个粗略的例子

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

,Users 表有 2 个外键,分别来自 UserID 和 FriendID。

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

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

如何确保强制实施这种完整性,也许是 2 个 PK?某种唯一索引?或者您会建议更好的桌子设计吗?另外,您会添加一个自动递增的 FriendshipID 吗?如果是这样,你能解释一下为什么吗?

Before you show me duplicates, please note that I've searched through the site an have found some examples but not quite specific to my problem :)

What's the best way to create a Friendship table in SQL, but making sure that each row is unique in the sense that the same UserID and FriendID will never be alowed regardless of which column they belong to?

I have this rough example

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

And there are 2 foreign keys to the Users table, both from UserID and FriendID.

At the moment though, I can insert a Friendship between users twice, thus creating a duplicate. Example

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

How do I ensure this integrity is enforced, perhaps 2 PKs? Some sort of a unique Index? Or would you suggest a better table design all together? Also, would you put an autoincrementing FriendshipID? If so, can you explain why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

挽清梦 2024-10-10 05:39:32
Table User: UserId
Table Friendship: FriendshipId
Table UserFriendships: UserId, FriendshipId, FriendshipStatus

您可以添加 UNIQUE 约束来防止用户两次处于友谊关系中。


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

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

You can add a UNIQUE constraint to prevent a User from being in a Friendship twice.


You have Users and Friendships. Users can join Friendships (which can be 0 or more Users) by creating a record in the third table.

递刀给你 2024-10-10 05:39:32

用户(用户ID)
Friendship(User1ID, User2ID, FriendshipStatus)

检查约束:User1ID < User2ID

唯一约束:User1ID、User2ID

User(UserID)
Friendship(User1ID, User2ID, FriendshipStatus)

Check constraint: User1ID < User2ID

Unique constraint: User1ID, User2ID

你的笑 2024-10-10 05:39:31

表的主键设置为:

  • useridfriendid
  • FRIENDSHIP

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

停止反向对

为了停止反向对(用户 ID“789”和朋友 ID“123”),您需要包含逻辑来检查该对是否已存在于存储过程、函数或触发器的表中。 userid < 的 CHECK 约束如果反向不存在,friendid 将停止添加用户 ID“789”和朋友 ID“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)

Making the primary key for the FRIENDSHIP table to be:

  • userid
  • friendid

...will ensure that you can't have duplicates in order. Meaning, it will stop you from adding duplicates of userid "123" and friendid "789". If you include the status column, that's no longer the case, because a different status value will allow for duplicates of the userid and friendid column.

Stopping Reverse Pairs

In order to stop reverse pairs -- userid "789" and friendid "123" -- you need to either include the logic to check if the pair already exists in the table in a stored procedure, function, or trigger. A CHECK constraint of userid < friendid would stop a valid attempt to add userid "789" and friendid "123" if the reverse doesn't already exist.

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)
葬花如无物 2024-10-10 05:39:31

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

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

Quassnoi wrote an article explaining why you might want to have a version of the table with two rows per pair, to make queries easier: http://explainextended.com/2009/03/07/selecting-friends/

(the article talks about MySQL but it is worth bearing in mind as a performance technique for any SQL database)

红墙和绿瓦 2024-10-10 05:39:31

我做了一个小更改来执行内部查询,并在末尾括号中存在时仅返回一条记录(双表)

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

I did a small change to perform the internal query and returns only a record when exists (dual table) at the end finish parentheses

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) )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文